<template>
  <view class="container">
    <!-- 页面加载状态 -->
    <view v-if="loading" class="page-loading-overlay">
      <view class="page-loading-content">
        <view class="loading-spinner">
          <view class="spinner large"></view>
        </view>
        <text class="loading-text">正在加载数据...</text>
      </view>
    </view>
    

    <!-- 当前播放状态栏 -->
    <view class="playing-status-bar">
      <view class="status-card">
        <view class="status-header">
          <view class="status-title-section">
            <text class="status-icon">🎵</text>
            <text class="status-title">播放控制台</text>
          </view>
          <view class="status-stats">
            <text class="stats-item">
              <text class="stats-label">总音频:</text>
              <text class="stats-value">{{ audioList.length }}</text>
            </text>
            <text class="stats-item">
              <text class="stats-label">播放中:</text>
              <text class="stats-value playing-count">{{ currentPlayingAudios.length }}</text>
            </text>
          </view>
        </view>

        <view class="status-content">
          <!-- 有音频播放时 -->
          <view v-if="currentPlayingAudios.length > 0" class="playing-content">
            <view class="playing-cards-container">
              <view
                v-for="(playingInfo, index) in currentPlayingAudios"
                :key="playingInfo.audio.id"
                class="playing-card"
                :class="{ 'card-primary': index === 0 }"
                @click="locateAudioInList(playingInfo)"
              >
                <view class="card-header">
                  <text class="category-icon">{{ playingInfo.categoryIcon }}</text>
                  <text class="category-name">{{ playingInfo.categoryName }}</text>
                  <view class="card-wave">
                    <text class="wave-dot">•</text>
                    <text class="wave-dot">•</text>
                    <text class="wave-dot">•</text>
                  </view>
                </view>
                <view class="card-content">
                  <view class="card-title-row">
                    <!-- 音频序号 -->
                    <view class="card-audio-index">
                      <view class="card-order-number playing">
                        {{ getAudioIndex(playingInfo.audio, playingInfo.categoryKey) }}
                      </view>
                    </view>
                    <text class="audio-name">{{ playingInfo.audio.name }}</text>
                  </view>
                  
                  <!-- 播放进度信息 -->
                  <view class="card-progress">
                    <!-- 进度条 -->
                    <view class="card-progress-bar">
                      <view class="card-progress-bg">
                        <view 
                          class="card-progress-fill" 
                          :style="{ width: (playingInfo.progress.progress || 0) + '%' }"
                        ></view>
                      </view>
                    </view>
                    
                    <!-- 时间和类型信息 -->
                    <view class="card-progress-info">
                      <text class="card-progress-time">
                        {{ formatPlayTime(playingInfo.progress.currentTime || 0) }} / {{ formatPlayTime(playingInfo.progress.duration || 0) }}
                      </text>
                      <text class="card-player-type" v-if="playingInfo.isMainPlayer">
                        🎵 分类播放
                      </text>
                    </view>
                  </view>
                  
                  <!-- 下一首播放计划 -->
                  <view v-if="nextPlaySchedule[playingInfo.categoryKey]" class="card-next-schedule">
                    <view class="schedule-header">
                      <text class="schedule-icon">⏭️</text>
                      <text class="schedule-label">下一首</text>
                      <view class="schedule-countdown">
                        <text class="countdown-time" v-if="nextPlaySchedule[playingInfo.categoryKey].countdown > 0">
                          {{ formatCountdown(nextPlaySchedule[playingInfo.categoryKey].countdown) }}
                        </text>
                        <text class="countdown-ready" v-else>
                          准备中...
                        </text>
                      </view>
                    </view>
                    <view class="schedule-content">
                      <text class="schedule-audio-name">
                        {{ (nextPlaySchedule[playingInfo.categoryKey].nextAudio && nextPlaySchedule[playingInfo.categoryKey].nextAudio.name) || '计算中...' }}
                      </text>
                      <text class="schedule-mode-info">
                        {{ getPlayModeText(playingInfo.categoryKey) }}
                      </text>
                    </view>
                  </view>
                </view>
              </view>
            </view>
          </view>

          <!-- 无音频播放时 -->
          <view v-else class="idle-content">
            <view class="idle-info">
              <text class="idle-icon">🎧</text>
              <text class="idle-text">暂无音频播放</text>
              <text class="idle-hint">点击任意音频的播放按钮开始播放</text>
            </view>
          </view>
        </view>
      </view>
    </view>

    <!-- 操作工具栏 -->
    <view class="toolbar">
      <view class="toolbar-card">
        <view class="toolbar-content">
          <view class="toolbar-info">
            <text class="playlist-title"
              >当前播放列表 ({{ audioList.length }}首)</text
            >
            <text class="playlist-hint"
              >💡 提示：点击🔄按钮可将音频移动到任意位置</text
            >
          </view>


          <view class="toolbar-actions">
            <el-button 
            type="info" 
            :icon="allCategoriesExpanded ? 'el-icon-folder' : 'el-icon-folder-opened'"
            @click="toggleAllCategories"
            size="small"
            style="margin-right: 10px;"
          >
            {{ allCategoriesExpanded ? '收起全部' : '展开全部' }}
          </el-button>
          <el-button 
          size="small"

              type="success" 
              icon="el-icon-folder-add"
              @click="handleAddCategoryClick"
            >
              添加分类
            </el-button>
           
            <el-button
            size="small"
              type="danger"
              icon="el-icon-video-pause"
              :disabled="!hasAnyPlaying"
              @click="stopAllAudios"
            >
              停止所有播放
            </el-button>
          </view>
        </view>
      </view>
    </view>

    <!-- 分类音频播放列表 -->
    <view class="audio-list-section">
      <!-- 分类列表 -->
      <scroll-view
        class="category-list"
        scroll-y="true"
        v-if="!loading && Object.keys(secondaryCategories).length > 0"
      >
        <view
          v-for="categoryKey in Object.keys(secondaryCategories)"
          :key="categoryKey"
          class="category-section"
        >
          <!-- 分类标题栏 -->
          <view class="category-header">
            <view class="category-header-left">
              <text class="category-icon">{{
                secondaryCategories[categoryKey].icon
              }}</text>
              <view class="category-title-info">
                <text class="category-title">{{
                  secondaryCategories[categoryKey].name
                }}</text>
                <text class="category-description">{{
                  secondaryCategories[categoryKey].description
                }}</text>
              </view>
              <view class="category-status">
                <text class="category-count"
                  >({{ (categorizedAudioList[categoryKey] || []).length }})</text
                >
                <view
                  v-if="getCategoryPlayStatus(categoryKey).playing"
                  class="playing-indicator"
                  :class="{ pulse: getCategoryPlayStatus(categoryKey).playing }"
                >
                  🔊 播放中
                </view>
              </view>
            </view>

            <view class="category-actions">
              <!-- 分类排序按钮组 -->
              <el-button-group class="category-sort-group">
                <el-button
                  size="small"
                  icon="el-icon-refresh"
                  :disabled="(categorizedAudioList[categoryKey] || []).length <= 1"
                  @click.stop="randomSortCategory(categoryKey)"
                  title="随机排序"
                >
                  随机排序
                </el-button>
               <!-- <el-button
                  size="small"
                  icon="el-icon-time"
                  :disabled="(categorizedAudioList[categoryKey] || []).length <= 1"
                  @click.stop="sortCategoryByDuration(categoryKey)"
                  title="时长排序"
                >
                  时长排序
                </el-button>
                <el-button
                  size="small"
                  icon="el-icon-sort"
                  :disabled="(categorizedAudioList[categoryKey] || []).length <= 1"
                  @click.stop="sortCategoryByName(categoryKey)"
                  title="名称排序"
                >
                  名称排序
                </el-button> -->
              </el-button-group>

              <!-- 分类音量控制 -->
              <view class="category-volume-control">
                <text class="volume-label">🔊</text>
                <el-slider
                  class="clean-volume-slider"
                  :value="getCategoryVolume(categoryKey)"
                  @input="onCategoryVolumeChange(categoryKey, $event)"
                  :min="0"
                  :max="100"
                  :step="10"
                  show-stops
                  :show-tooltip="true"
                  :format-tooltip="formatVolumeTooltip"
                ></el-slider>
                <view class="category-volume-display">
                  <text class="category-volume-value">{{ Math.round(getCategoryVolume(categoryKey)) }}%</text>
                  <text class="category-volume-hint">控制全部</text>
                </view>
              </view>

              <!-- 分类控制按钮组 -->
              <el-button-group class="category-ctrl-group">
                <el-button
                  size="small"
                  type="primary"
                  icon="el-icon-plus"
                  @click.stop="showAudioPicker(categoryKey)"
                  title="添加音频"
                >
                  添加音频
                </el-button>
                <el-button
                  size="small"
                  type="warning"
                  icon="el-icon-setting"
                  @click.stop="showCategoryConfig(categoryKey)"
                  title="分类设置"
                >
                  设置
                </el-button>
                <el-button
                  size="small"
                  :type="getCategoryPlayStatus(categoryKey).playing ? 'warning' : 'primary'"
                  :icon="getCategoryPlayStatus(categoryKey).playing ? 'el-icon-video-pause' : 'el-icon-video-play'"
                  :disabled="(categorizedAudioList[categoryKey] || []).length === 0"
                  @click.stop="toggleCategoryPlay(categoryKey)"
                  :title="getCategoryPlayStatus(categoryKey).playing ? '暂停播放' : '开始播放'"
                >
                  {{ getCategoryPlayStatus(categoryKey).playing ? "暂停" : "播放" }}
                </el-button>
               <!-- <el-button
                  size="small"
                  type="info"
                  icon="el-icon-switch-button"
                  :disabled="!getCategoryPlayStatus(categoryKey).playing"
                  @click.stop="stopCategoryAudios(categoryKey)"
                  title="停止播放"
                >
                  停止
                </el-button> -->
                <el-button
                  size="small"
                  type="danger"
                  icon="el-icon-delete"
                  :disabled="getCategoryPlayStatus(categoryKey).playing"
                  @click.stop="handleDeleteCategoryClick(categoryKey)"
                  :title="getCategoryPlayStatus(categoryKey).playing ? '请先停止播放再删除分类' : '删除分类'"
                >
                  删除
                </el-button>
              </el-button-group>

              <!-- 展开折叠按钮 -->
              <el-button
                size="small"
                :icon="secondaryCategories[categoryKey].expanded ? 'el-icon-folder-opened' : 'el-icon-folder'"
                @click.stop="toggleCategoryExpanded(categoryKey)"
              >
                {{ secondaryCategories[categoryKey].expanded ? "收起" : "展开" }}
              </el-button>
            </view>
          </view>

          <!-- 分类音频列表 -->
          <view
            v-show="secondaryCategories[categoryKey].expanded"
            class="category-content"
          >
            <!-- 移动模式：顶部插入区域 -->
            <view 
              v-if="moveMode && movingCategoryKey === categoryKey"
              class="insert-zone top-insert"
              @click.stop="insertAtPosition(categoryKey, 0)"
            >
              <view class="insert-position-info">
                <text class="position-label">插入位置：第1位（顶部）</text>
              </view>
              <view class="insert-btn">
                <text class="insert-icon">⬆️</text>
                <text class="insert-text">插入到第1位</text>
              </view>
            </view>

            <view
              v-for="(audio, index) in (categorizedAudioList[categoryKey] || [])"
                :key="audio.id"
              class="audio-item-wrapper"
            >
              <view
                :id="'audio-item-' + audio.id"
                class="audio-item"
                :class="{
                  playing: audio.isPlaying,
                  moving: moveMode && movingCategoryKey === categoryKey && movingAudioIndex === index,
                  'move-disabled': moveMode && movingCategoryKey !== categoryKey,
                  'audio-highlighted': highlightedAudioId === audio.id,
                  'volume-updated': audio.volumeUpdated
                }"
              >
              <view class="audio-content">
                <!-- 序号 -->
                <view class="audio-index">
                  <view
                    class="order-number"
                    :class="{ playing: audio.isPlaying }"
                  >
                    {{ audio.isPlaying ? "🔊" : index + 1 }}
                  </view>
                </view>

                <!-- 音频信息 -->
                <view class="audio-info">
                  <view
                    class="audio-name"
                    :class="{ playing: audio.isPlaying }"
                  >
                    {{ audio.name }}
                  </view>
                  <view class="audio-meta">
                    <text class="audio-category">{{
                      audio.category || "未分类"
                    }}</text>
                    <text class="audio-duration">{{
                      formatDuration(audio.duration)
                    }}</text>
                    <text v-if="audio.isPlaying" class="playing-status">
                      正在播放...
                    </text>
                  </view>
                </view>

                 <!-- 操作按钮 -->
                 <view class="audio-actions">
                   <!-- 正常模式按钮 -->
                   <template v-if="!moveMode">
                     <!-- 音频音量控制 -->
                     <view class="audio-volume-control">
                       <text class="volume-icon">🔊</text>
                       <el-slider
                         class="clean-audio-volume-slider"
                         :value="getAudioVolume(audio.id)"
                         @input="onAudioVolumeChange(audio.id, $event)"
                         :min="0"
                         :max="100"
                         :step="10"
                         show-stops
                         :show-tooltip="true"
                         :format-tooltip="formatVolumeTooltip"
                       ></el-slider>
                       <view class="volume-display">
                         <text class="volume-percent">{{ Math.round(getAudioVolume(audio.id)) }}%</text>
                         <!-- 自定义状态指示区域 - 固定宽度避免布局跳动 -->
                         <view class="custom-status-area">
                           <text 
                             v-if="isAudioVolumeCustomized(audio.id)" 
                             class="custom-indicator"
                             title="音量已自定义"
                           >🔒</text>
                           <text v-else class="custom-indicator-placeholder"></text>
                         </view>
                         <!-- 重置按钮区域 - 固定宽度避免布局跳动 -->
                         <view class="reset-button-area">
                           <el-button 
                             v-if="isAudioVolumeCustomized(audio.id)"
                             size="mini" 
                             type="text" 
                             icon="el-icon-refresh-left"
                             @click="resetAudioVolumeToCategory(audio.id, categoryKey)"
                             title="重置到分类音量"
                             class="reset-button"
                           >
                           </el-button>
                         </view>
                       </view>
                     </view>
                     
                     <el-button
                       size="mini"
                       :type="audio.isPlaying ? 'warning' : 'primary'"
                       :icon="audio.isPlaying ? 'el-icon-video-pause' : 'el-icon-video-play'"
                       @click="simpleToggleAudioPlay(audio.id, categoryKey)"
                       :title="audio.isPlaying ? '停止播放' : '开始播放'"
                       circle
                     >
                     </el-button>
                    <!-- <el-button
                       size="mini"
                       type="info"
                       icon="el-icon-view"
                       @click="previewAudio(audio)"
                       title="预览"
                       circle
                     >
                     </el-button> -->
                     <el-button
                       size="mini"
                       icon="el-icon-refresh"
                       @click="enterCategoryMoveMode(categoryKey, index)"
                       title="移动排序"
                       :disabled="(categorizedAudioList[categoryKey] || []).length <= 1"
                       circle
                     >
                     </el-button>
                     <el-button 
                       size="mini"
                       type="danger"
                       icon="el-icon-delete"
                       :loading="removingAudioIds.has(audio.id)"
                       :disabled="removingAudioIds.has(audio.id)"
                       @click="removeAudio(audio.id, categoryKey)"
                       :title="removingAudioIds.has(audio.id) ? '正在删除...' : '删除'"
                       circle
                     >
                     </el-button>
                   </template>

                    <!-- 移动模式：显示正在移动的项目或取消按钮 -->
                    <template v-else-if="moveMode && movingCategoryKey === categoryKey && movingAudioIndex === index">
                      <view class="moving-indicator"> 
                        <text class="moving-icon">🔴</text>
                        <text class="moving-text">正在移动该项</text>
                      </view>
                      <el-button
                        size="small"
                        type="warning"
                        icon="el-icon-close"
                        @click.stop="cancelMove"
                        title="取消移动"
                        class="cancel-move-btn"
                      >
                        取消移动
                      </el-button>
                      </template>

                    <!-- 移动模式：其他分类显示禁用状态 -->
                    <template v-else-if="moveMode && movingCategoryKey !== categoryKey">
                      <view class="disabled-indicator"> 
                        <text class="disabled-icon">⚪</text>
                        <text class="disabled-text">只能在同分类内移动</text>
                      </view>
                  </template> 
                </view>
                </view>
              </view>

              <!-- 移动模式：在每个项目下方添加插入区域 -->
              <view 
                v-if="moveMode && movingCategoryKey === categoryKey && movingAudioIndex !== index"
                class="insert-zone"
                @click.stop="insertAtPosition(categoryKey, index + 1)"
              >
                <view class="insert-position-info">
                  <text class="position-label">插入位置：第{{ index + 2 }}位（在"{{ audio.name }}"下方）</text>
                </view>
                <view class="insert-btn">
                  <text class="insert-icon">⬇️</text>
                  <text class="insert-text">插入到第{{ index + 2 }}位</text>
                </view>
              </view>
            </view>

            <!-- 移动模式：底部插入区域 -->
            <view 
              v-if="moveMode && movingCategoryKey === categoryKey"
              class="insert-zone bottom-insert"
              @click.stop="insertAtPosition(categoryKey, (categorizedAudioList[categoryKey] || []).length)"
            >
              <view class="insert-position-info">
                <text class="position-label">插入位置：第{{ (categorizedAudioList[categoryKey] || []).length + 1 }}位（底部）</text>
              </view>
              <view class="insert-btn">
                <text class="insert-icon">⬇️</text>
                <text class="insert-text">插入到第{{ (categorizedAudioList[categoryKey] || []).length + 1 }}位</text>
              </view>
            </view>

            <!-- 分类空状态 -->
            <view
              v-if="(categorizedAudioList[categoryKey] || []).length === 0"
              class="category-empty"
            >
              <text class="empty-text">该分类暂无音频</text>
              <text class="empty-hint">点击上方"添加音频"按钮开始添加</text>
            </view>
          </view>
        </view>
      </scroll-view>

      <!-- 总体空状态 - 无分类时 -->
      <view v-if="Object.keys(secondaryCategories).length === 0 && !loading" class="empty-state">
        <text class="empty-title">🎵 暂无音频分类</text>
        <text class="empty-desc">先创建分类，再添加音频，打造专属的直播音效库吧！</text>
        <el-button 
          type="primary" 
          size="medium" 
          icon="el-icon-plus" 
          @click="handleAddCategoryClick"
        >
          添加第一个分类
        </el-button>
      </view>

      <!-- 加载状态 -->
      <view v-if="loading" class="loading-state">
        <view class="loading-spinner">🔄</view>
        <text>加载音频列表中...</text>
      </view>
    </view>

    <!-- 分类配置弹窗 -->
    <el-dialog
      top="2vh"
      :visible.sync="categoryConfigVisible"
      :title="currentConfigCategory ? secondaryCategories[currentConfigCategory].name + ' 配置' : '分类配置'"
      width="600px"
      :close-on-click-modal="true"
      :close-on-press-escape="true"
      append-to-body
      destroy-on-close
      :show-close="false"
      center
      class="category-config-dialog"
    >
      <template slot="title">
        <view class="dialog-title-wrapper">
          <text class="config-icon">{{
            currentConfigCategory
              ? secondaryCategories[currentConfigCategory].icon
              : "⚙️"
          }}</text>
          <view class="config-title-text">
            <text class="config-title">{{
              currentConfigCategory
                ? secondaryCategories[currentConfigCategory].name
                : ""
            }} 配置</text>
            <text class="config-subtitle">自定义播放行为和参数</text>
          </view>
        </view>
      </template>

        <view class="config-content" v-if="currentConfigCategory">
          <!-- 播放模式配置 -->
          <view class="config-section">
            <view class="config-section-title">
              <text class="section-icon">🎮</text>
              <text>播放模式</text>
            </view>
            <view class="config-options">
              <view
                class="config-option"
                :class="{
                  active:
                    secondaryCategories[currentConfigCategory].config
                      .playMode === 'sequential',
                }"
                @click="updateLocalConfig('playMode', 'sequential')"
              >
                <view class="option-icon">📃</view>
                <view class="option-info">
                  <text class="option-title">顺序播放</text>
                  <text class="option-desc">按列表顺序依次播放</text>
                </view>
              </view>
              <view
                class="config-option"
                :class="{
                  active:
                    secondaryCategories[currentConfigCategory].config
                      .playMode === 'random',
                }"
                @click="updateLocalConfig('playMode', 'random')"
              >
                <view class="option-icon">🔀</view>
                <view class="option-info">
                  <text class="option-title">随机播放</text>
                  <text class="option-desc">随机选择音频播放</text>
                </view>
              </view>
              <view
                class="config-option"
                :class="{
                  active:
                    secondaryCategories[currentConfigCategory].config
                      .playMode === 'loop',
                }"
                @click="updateLocalConfig('playMode', 'loop')"
              >
                <view class="option-icon">🔂</view>
                <view class="option-info">
                  <text class="option-title">循环播放</text>
                  <text class="option-desc">单曲循环或列表循环</text>
                </view>
              </view>
              <view
                class="config-option"
                :class="{
                  active:
                    secondaryCategories[currentConfigCategory].config
                      .playMode === 'manual',
                }"
                @click="updateLocalConfig('playMode', 'manual')"
              >
                <view class="option-icon">✋</view>
                <view class="option-info">
                  <text class="option-title">手动播放</text>
                  <text class="option-desc">仅手动控制播放</text>
                </view>
              </view>
            </view>
          </view>

          <!-- 播放间隔配置 -->
          <view class="config-section">
            <view class="config-section-title">
              <text class="section-icon">⏰</text>
              <text>播放间隔</text>
            </view>
            <view class="config-input-group">
              <view class="input-row">
                <view class="input-item half-width">
                  <text class="input-label">最小间隔</text>
                  <view class="input-container">
                    <el-input-number
                      class="config-input"
                      v-model="secondaryCategories[currentConfigCategory].config.intervalMin"
                      placeholder="最小"
                      :min="0"
                      :max="secondaryCategories[currentConfigCategory].config.intervalMax || 9999"
                      :step="1"
                      controls-position="right"
                    ></el-input-number>
                    <text class="input-unit">秒</text>
                  </view>
                </view>
                
                <view class="interval-separator">
                  <text class="separator-text">到</text>
                </view>
                
                <view class="input-item half-width">
                  <text class="input-label">最大间隔</text>
                  <view class="input-container">
                    <el-input-number
                      class="config-input"
                      v-model="secondaryCategories[currentConfigCategory].config.intervalMax"
                      placeholder="最大"
                      :min="secondaryCategories[currentConfigCategory].config.intervalMin || 0"
                      :max="9999"
                      :step="1"
                      controls-position="right"
                    ></el-input-number>
                    <text class="input-unit">秒</text>
                  </view>
                </view>
              </view>
              
              <view class="interval-preview">
                <text class="preview-label">播放间隔：</text>
                <text class="preview-value">
                  {{ 
                    secondaryCategories[currentConfigCategory].config.intervalMin === 
                    secondaryCategories[currentConfigCategory].config.intervalMax
                    ? `固定 ${secondaryCategories[currentConfigCategory].config.intervalMin} 秒`
                    : `随机 ${secondaryCategories[currentConfigCategory].config.intervalMin}-${secondaryCategories[currentConfigCategory].config.intervalMax} 秒`
                  }}
                </text>
              </view>
              
              <view class="input-hint">
                <text class="hint-text">💡 两个值相等表示固定间隔，不同则在范围内随机选择。设置为0表示无间隔连续播放</text>
              </view>
            </view>
          </view>

          <!-- 随机片段播放配置 -->
          <view class="config-section">
            <view class="config-section-title">
              <text class="section-icon">🎲</text>
              <text>随机片段播放</text>
            </view>
            <view class="config-switch-group">
              <view class="switch-item">
                <view class="switch-info">
                  <text class="switch-title">启用随机片段播放</text>
                  <text class="switch-desc">每次只播放音频的随机片段，大幅降低重复率</text>
                </view>
                <switch
                  :checked="
                    secondaryCategories[currentConfigCategory].config.randomFragment
                  "
                  @change="onRandomFragmentChange"
                  color="#10b981"
                />
              </view>
            </view>
            
            <!-- 快捷设置选项 -->
            <view 
              v-if="secondaryCategories[currentConfigCategory].config.randomFragment"
              class="fragment-quick-settings"
            >
              <text class="quick-settings-label">快捷设置:</text>
              <view class="quick-settings-buttons">
                <view
                  class="quick-setting-btn conservative"
                  @click="applyFragmentPreset('conservative')"
                >
                  <text class="preset-icon">🛡️</text>
                  <text class="preset-name">保守模式</text>
                  <text class="preset-desc">20%概率·温和降重</text>
                </view>
                <view
                  class="quick-setting-btn balanced"
                  @click="applyFragmentPreset('balanced')"
                >
                  <text class="preset-icon">⚖️</text>
                  <text class="preset-name">平衡模式</text>
                  <text class="preset-desc">35%概率·推荐日用</text>
                </view>
                <view
                  class="quick-setting-btn aggressive"
                  @click="applyFragmentPreset('aggressive')"
                >
                  <text class="preset-icon">🚀</text>
                  <text class="preset-name">激进模式</text>
                  <text class="preset-desc">60%概率·最大降重</text>
                </view>
                <view
                  class="quick-setting-btn stealth"
                  @click="applyFragmentPreset('stealth')"
                >
                  <text class="preset-icon">🥷</text>
                  <text class="preset-name">隐蔽模式</text>
                  <text class="preset-desc">45%概率·避检测</text>
                </view>
              </view>
            </view>

            <!-- 随机片段详细配置 -->
            <view 
              v-if="secondaryCategories[currentConfigCategory].config.randomFragment"
              class="config-input-group random-fragment-settings"
            >
              <view class="input-row">
                <view class="input-item half-width">
                  <text class="input-label">最短播放</text>
                  <view class="input-container">
                    <el-input-number
                      class="config-input"
                      v-model="secondaryCategories[currentConfigCategory].config.fragmentMinDuration"
                      placeholder="最短"
                      :min="1"
                      :max="secondaryCategories[currentConfigCategory].config.fragmentMaxDuration || 30"
                      :step="1"
                      controls-position="right"
                      @change="onFragmentMinDurationChange"
                    ></el-input-number>
                    <text class="input-unit">秒</text>
                  </view>
                </view>
                
                <view class="interval-separator">
                  <text class="separator-text">到</text>
                </view>
                
                <view class="input-item half-width">
                  <text class="input-label">最长播放</text>
                  <view class="input-container">
                    <el-input-number
                      class="config-input"
                      v-model="secondaryCategories[currentConfigCategory].config.fragmentMaxDuration"
                      placeholder="最长"
                      :min="secondaryCategories[currentConfigCategory].config.fragmentMinDuration || 1"
                      :max="60"
                      :step="1"
                      controls-position="right"
                      @change="onFragmentMaxDurationChange"
                    ></el-input-number>
                    <text class="input-unit">秒</text>
                  </view>
                </view>
              </view>
              
              <view class="input-row">
                <view class="input-item half-width">
                  <text class="input-label">触发概率</text>
                  <view class="input-container">
                    <el-input-number
                      class="config-input"
                      v-model="secondaryCategories[currentConfigCategory].config.fragmentProbability"
                      placeholder="概率"
                      :min="10"
                      :max="90"
                      :step="5"
                      controls-position="right"
                    ></el-input-number>
                    <text class="input-unit">%</text>
                  </view>
                </view>
                
                <view class="interval-separator">
                  <text class="separator-text">当</text>
                </view>
                
                <view class="input-item half-width">
                  <text class="input-label">音频长度 ≥</text>
                  <view class="input-container">
                    <el-input-number
                      class="config-input"
                      v-model="secondaryCategories[currentConfigCategory].config.fragmentMinAudioLength"
                      placeholder="最小长度"
                      :min="10"
                      :max="60"
                      :step="5"
                      controls-position="right"
                    ></el-input-number>
                    <text class="input-unit">秒</text>
                  </view>
                </view>
              </view>
              
              <view class="input-row">
                <view class="input-item">
                  <text class="input-label">起始位置策略</text>
                  <view class="fragment-strategy-options">
                    <view
                      class="strategy-option"
                      :class="{ active: secondaryCategories[currentConfigCategory].config.fragmentStartStrategy === 'random' }"
                      @click="updateLocalConfig('fragmentStartStrategy', 'random')"
                    >
                      <text class="strategy-icon">🎯</text>
                      <text class="strategy-name">完全随机</text>
                    </view>
                    <view
                      class="strategy-option"
                      :class="{ active: secondaryCategories[currentConfigCategory].config.fragmentStartStrategy === 'avoid_start' }"
                      @click="updateLocalConfig('fragmentStartStrategy', 'avoid_start')"
                    >
                      <text class="strategy-icon">⚡</text>
                      <text class="strategy-name">避开开头</text>
                    </view>
                    <view
                      class="strategy-option"
                      :class="{ active: secondaryCategories[currentConfigCategory].config.fragmentStartStrategy === 'middle_focus' }"
                      @click="updateLocalConfig('fragmentStartStrategy', 'middle_focus')"
                    >
                      <text class="strategy-icon">🎪</text>
                      <text class="strategy-name">中段优先</text>
                    </view>
                  </view>
                </view>
              </view>
              
              <view class="fragment-preview">
                <text class="preview-label">播放效果：</text>
                <text class="preview-value">
                  {{ getFragmentPreviewText(currentConfigCategory) }}
                </text>
              </view>
              
              <view class="input-hint">
                <text class="hint-text">💡 当音频≥{{ secondaryCategories[currentConfigCategory].config.fragmentMinAudioLength }}秒时，{{ secondaryCategories[currentConfigCategory].config.fragmentProbability }}%概率播放{{ secondaryCategories[currentConfigCategory].config.fragmentMinDuration }}-{{ secondaryCategories[currentConfigCategory].config.fragmentMaxDuration }}秒片段，短音频直接完整播放</text>
              </view>
            </view>
          </view>

          <!-- 自动播放配置 -->
          <view class="config-section">
            <view class="config-section-title">
              <text class="section-icon">🚀</text>
              <text>自动播放</text>
            </view>
            <view class="config-switch-group">
              <view class="switch-item">
                <view class="switch-info">
                  <text class="switch-title">启用自动播放</text>
                  <text class="switch-desc">音频播放结束后自动播放下一个</text>
                </view>
                <switch
                  :checked="
                    secondaryCategories[currentConfigCategory].config.autoPlay
                  "
                  @change="onAutoPlayChange"
                  color="#10b981"
                />
              </view>
            </view>
          </view>


          <!-- 并发播放限制 -->
          <view class="config-section">
            <view class="config-section-title">
              <text class="section-icon">🎯</text>
              <text>并发限制</text>
            </view>
            <view class="config-number-group">
              <text class="number-label">同时最多播放</text>
              <view class="number-controls">
                <el-button
                  size="mini"
                  type="primary"
                  plain
                  icon="el-icon-minus"
                  :disabled="
                    secondaryCategories[currentConfigCategory].config
                      .maxConcurrent <= 1
                  "
                  @click="
                    updateLocalConfig(
                      'maxConcurrent',
                      secondaryCategories[currentConfigCategory].config
                        .maxConcurrent - 1
                    )
                  "
                >
                </el-button>
                <text class="number-value">{{
                  secondaryCategories[currentConfigCategory].config
                    .maxConcurrent
                }}</text>
                <el-button
                  size="mini"
                  type="primary"
                  plain
                  icon="el-icon-plus"
                  :disabled="
                    secondaryCategories[currentConfigCategory].config
                      .maxConcurrent >= 5
                  "
                  @click="
                    updateLocalConfig(
                      'maxConcurrent',
                      secondaryCategories[currentConfigCategory].config
                        .maxConcurrent + 1
                    )
                  "
                >
                </el-button>
              </view>
              <text class="number-unit">个音频</text>
            </view>
          </view>

        </view>
      
      <div slot="footer" class="dialog-footer">
        <el-button 
          icon="el-icon-refresh-right"
          @click="resetCategoryConfig"
        >
          重置默认
        </el-button>
        <el-button 
          type="success" 
          icon="el-icon-check"
          @click="saveCategoryConfig"
        >
          保存配置
        </el-button>
      </div>
    </el-dialog>

    <!-- 音频选择弹窗 -->
    <el-dialog
      title="选择音频文件"
      :visible.sync="audioPickerVisible"
      width="800px"
      :before-close="closeAudioPicker"
      custom-class="audio-picker-dialog"
      top="2vh"
    >

        <view class="picker-content">
          <!-- 搜索筛选 -->
          <view class="picker-filter">
            <el-input
              v-model="searchText"
              placeholder="搜索音频文件..."
              class="search-input"
              @input="onSearchChange"
              clearable
              prefix-icon="el-icon-search"
            ></el-input>
            <view class="category-select-container">
              <el-select 
                v-model="selectedCategory"
                class="category-select" 
                @change="onCategoryChange"
                placeholder="请选择分类"
                clearable
              >
                <el-option
                  v-for="option in categoryOptionsWithCount"
                  :key="option.value"
                  :value="option.value"
                  :label="option.label"
                >
                </el-option>
              </el-select>
              <view v-if="categoriesLoading" class="category-loading">
                <view class="spinner small"></view>
              </view>
             
            </view>
          </view>

          <!-- 分类选择区域 - 显眼位置 -->
          <!-- <view  class="category-selector-top" v-if="selectedCount > 0">
            <view class="selector-header">
              <text class="selector-icon">📂</text>
              <text class="selector-title">添加到分类：</text>
            </view>
            <el-select 
              v-model="selectedTargetCategory" 
              placeholder="选择目标分类"
              style="width: 180px;"
              size="small"
            >
              <el-option
                v-for="(category, key) in secondaryCategories"
                :key="key"
                :label="category.name"
                :value="key"
              >
              </el-option>
            </el-select>
            <text class="selected-info">已选择 {{ selectedCount }} 个音频</text>
          </view> -->

          <!-- 多选操作栏 -->
          <view class="multi-select-toolbar">
            <view class="select-all-section">
              <el-button 
                size="small"
                :type="isAllSelected ? 'warning' : 'primary'"
                :icon="isAllSelected ? 'el-icon-close' : 'el-icon-check'"
                @click="toggleSelectAll"
              >
                {{ isAllSelected ? '取消全选' : '全选' }}
              </el-button>
              <text class="selected-count">已选择: {{ selectedCount }} / {{ filteredAvailableAudios.length }}</text>
            </view>
          </view>

          <!-- 可选音频列表 -->
          <scroll-view class="available-list" scroll-y="true">
            
            <!-- 加载状态 -->
            <view v-if="availableAudiosLoading" class="audio-list-loading">
              <view class="loading-spinner">
                <view class="spinner"></view>
              </view>
              <text class="loading-text">正在加载音频列表...</text>
            </view>
            
            <!-- 音频列表 -->
            <view
              v-else
              v-for="audio in filteredAvailableAudios"
              :key="audio.id"
              class="available-item"
              :class="{ 'selected': selectedAudioIds.has(audio.id) }"
              @click="toggleAudioSelection(audio.id)"
            >
              <!-- 选择框 -->
              <view class="selection-checkbox">
                <view class="checkbox-icon" :class="{ 'checked': selectedAudioIds.has(audio.id) }">
                  <text v-if="selectedAudioIds.has(audio.id)" class="check-mark">✓</text>
                </view>
              </view>

              <view class="available-info">
                <view class="available-name">{{ audio.name }}</view>
                <view class="available-meta">
                  <text class="available-category">{{
                    audio.category || "根目录"
                  }}</text>
                  <text class="available-duration">{{
                    formatDuration(audio.duration)
                  }}</text>
                </view>
                
                <!-- 播放进度显示 -->
                <view v-if="audio.isPlaying || (previewingAudioId === audio.id && isAudioLoading)" class="play-progress">
                  <!-- 加载状态 -->
                  <view v-if="previewingAudioId === audio.id && isAudioLoading" class="loading-state">
                    <text class="loading-text">加载中...</text>
                  </view>
                  
                  <!-- 播放进度 -->
                  <view v-else-if="audio.isPlaying" class="progress-container">
                    <view class="progress-info">
                      <text class="progress-time">{{ formatPlayTime(currentTime) }} / {{ formatPlayTime(totalDuration) }}</text>
                    </view>
                    <view class="progress-bar">
                      <view class="progress-bg">
                        <view class="progress-fill" :style="{ width: playProgress + '%' }"></view>
                      </view>
                    </view>
                  </view>
                </view>
              </view>
              <view class="available-actions">
                <el-button
                  size="mini"
                  :type="audio.isPlaying ? 'warning' : 'primary'"
                  :icon="getAudioButtonIcon(audio)"
                  @click.stop="togglePreviewAudio(audio)"
                >
                  {{ getAudioButtonText(audio) }}
                </el-button>
              </view>
            </view>

            <!-- 空状态 -->
            <view
              v-if="!availableAudiosLoading && filteredAvailableAudios.length === 0"
              class="empty-state"
            >
              <text>暂无可用音频</text>
              <text>请检查音频文件或搜索条件</text>
            </view>
          </scroll-view>

          <!-- 底部操作栏 -->
          <view class="picker-footer">
            <el-button @click="handleCloseAudioPicker">
              取消
            </el-button>
            <el-button 
              type="warning" 
              :disabled="selectedCount === 0"
              @click="clearSelection"
            >
              清空选择
            </el-button>
            <el-button 
              type="primary" 
              :loading="addingAudios"
              :disabled="selectedCount === 0 || addingAudios"
              @click="addSelectedAudios"
            >
              <span v-if="addingAudios">正在添加...</span>
              <span v-else>添加选中 ({{ selectedCount }})</span>
            </el-button>
          </view>
        </view>
    </el-dialog>

    <!-- 添加分类弹窗 -->
    <el-dialog
      :visible.sync="addCategoryVisible"
      title="添加音频分类"
      width="500px"
      top="5vh"
      :close-on-click-modal="true"
      :close-on-press-escape="true"
      append-to-body
      destroy-on-close
      class="add-category-dialog"
      @closed="onAddCategoryClosed"
    >
      <template slot="title">
        <view class="dialog-title-wrapper">
          <text class="config-icon">📁</text>
          <view class="config-title-text">
            <text class="config-title">添加音频分类</text>
            <text class="config-subtitle">创建新的音频分类便于管理</text>
          </view>
        </view>
      </template>

        <view class="popup-content">
          <!-- 分类名称 -->
          <view class="form-section">
            <text class="form-label">分类名称 *</text>
            <view class="input-wrapper">
              <el-input
                v-model="newCategory.name"
                placeholder="请输入分类名称（如：游戏音效）"
                class="form-input"
                maxlength="20"
                clearable
              />
            </view>
          </view>

          <!-- 分类描述 -->
          <view class="form-section">
            <text class="form-label">分类描述</text>
            <el-input
              v-model="newCategory.description"
              placeholder="请输入分类描述（如：游戏相关的音效和背景音乐）"
              class="form-textarea"
              maxlength="100"
              type="textarea"
              :rows="3"
              resize="none"
            ></el-input>
          </view>

          <!-- 图标选择 -->
          <view class="form-section">
            <text class="form-label">选择图标</text>
            <view class="icon-grid">
              <view
                v-for="icon in categoryIcons"
                :key="icon"
                class="icon-item"
                :class="{ active: newCategory.icon === icon }"
                @click="selectIcon(icon)"
              >
                <text class="icon-text">{{ icon }}</text>
              </view>
            </view>
          </view>
        </view>
      
      <div slot="footer" class="dialog-footer">
        <el-button 
          size="medium"
          @click="closeAddCategory"
        >
          取消
        </el-button>
        <el-button 
          type="primary"
          size="medium"
          :loading="addCategoryLoading"
          :disabled="!newCategory.name.trim() || addCategoryLoading"
          @click="confirmAddCategory"
        >
          {{ addCategoryLoading ? '创建中...' : '创建分类' }}
        </el-button>
      </div>
    </el-dialog>
  </view>
</template>

<script>
import {
  getRoomConfigs,
  updateRoomConfig,
  getRoomAudios,
  addAudioToRoom,
  addMultipleAudiosToRoom,
  removeAudioFromRoom,
  updateAudioSort,
  createRoomCategory,
  deleteRoomCategory,
  updateAudioVolume,
  updateMultipleAudioVolumes
} from '@/api/roomAudioConfig.js'

import audioAPI from '@/api/audio.js'
import { AudioPlayer } from '@/utils/audioPlayer.js'

export default {
  data() {
    return {
      // 加载状态
      loading: false,
      availableAudiosLoading: false, // 可选音频列表加载状态
      categoriesLoading: false, // 分类目录加载状态
      addingAudios: false, // 添加音频操作加载状态
      addCategoryLoading: false, // 创建分类操作加载状态
      removingAudioIds: new Set(), // 正在删除的音频ID集合
      isInitializing: false, // 是否正在初始化（防止初始化时触发接口调用）
      isCategoryVolumeChanging: false, // 是否正在进行分类音量变化（防止连锁反应）
      customAudioVolumes: new Set(), // 记录用户手动设置过音量的音频ID
      customAudioVolumesTrigger: 0, // 用于触发Vue响应式更新的计数器
      
      // 简单播放器状态管理 
      playingAudiosByCategory: {}, // 每个分类当前播放的音频ID
      audioPlayerInstances: {}, // 每个分类的音频播放器实例
      audioTimers: {}, // 音频播放定时器管理
      globalAudioTimers: [], // 全局定时器数组，用于统一管理
      
      // 音量控制管理
      audioVolumes: {}, // 单个音频的音量设置 {audioId: volume}
      categoryVolumes: {}, // 分类级别的音量设置 {categoryKey: volume}
      volumeSaveTimers: {}, // 音量保存防抖定时器 {audioId: timer}
      categoryVolumeSaveTimers: {}, // 分类音量保存防抖定时器 {categoryKey: timer}
      
      // 分类音频播放进度管理
      categoryPlayProgress: {}, // 每个分类当前播放音频的进度信息
      
      // 下一首播放计划管理
      nextPlaySchedule: {}, // 每个分类的下一首播放计划 {categoryKey: {nextAudio, countdown, totalInterval}}
      countdownTimers: {}, // 倒计时定时器管理

      // 当前房间
      currentRoom: {
        id: "2",
        name: "游戏直播",
      },

      // 二级分类定义
      secondaryCategories: {
        // scene: {
        //   name: "场景音频",
        //   description: "欢迎语、感谢语、互动等场景音频",
        //   icon: "🎭",
        //   subCategories: [
        //     "欢迎语",
        //     "感谢语",
        //     "互动语",
        //     "活动语",
        //     "节日语",
        //     "提醒语",
        //   ],
        //   config: {
        //     playMode: "sequential", // sequential: 顺序播放, random: 随机播放
        //     intervalMin: 20, // 播放间隔最小时间(秒)
        //     intervalMax: 40, // 播放间隔最大时间(秒)
        //     autoPlay: true, // 是否自动播放
        //     maxConcurrent: 1, // 同时播放数量限制
        //   },
        //   expanded: true, // 是否展开显示
        // },
        // background: {
        //   name: "背景音乐",
        //   description: "直播间背景音乐",
        //   icon: "🎵",
        //   subCategories: ["背景音乐"],
        //   config: {
        //     playMode: "loop", // loop: 循环播放
        //     intervalMin: 0, // 无间隔最小时间
        //     intervalMax: 0, // 无间隔最大时间
        //     autoPlay: false,
        //     maxConcurrent: 1,
        //     volume: 0.3, // 背景音乐音量
        //   },
        //   expanded: true,
        // },
        // other: {
        //   name: "其他音频",
        //   description: "未分类的音频文件",
        //   icon: "🎧",
        //   subCategories: [],
        //   config: {
        //     playMode: "manual", // manual: 手动播放
        //     intervalMin: 5,
        //     intervalMax: 15,
        //     autoPlay: false,
        //     maxConcurrent: 1,
        //   },
        //   expanded: true,
        // },
      },

      // 当前播放列表 (按二级分类组织)
      audioList: [],

      // 分类后的音频列表
      categorizedAudioList: {
        scene: [],
        background: [],
        other: [],
      },

      // 原始音频数据 (已删除测试数据，现在通过API获取)
      rawAudioList: [
      ],

      // 可用音频库 (更丰富的音频资源)  
      availableAudios: [
        // {
        //   id: "1003",
        //   name: "掌声音效.mp3",
        //   category: "音效",
        //   duration: 6,
        //   path: "/audio/applause.mp3",
        // },
      ],

      // 搜索筛选
      searchText: "",
      selectedCategory: "",
      categoryOptions: [
        {
          label: "全部分类",
          value: "",
        },
      ],
      folderList: [], // 文件夹列表数据

      // 弹窗控制
      audioPickerVisible: false,
      categoryConfigVisible: false,
      addCategoryVisible: false,
      currentConfigCategory: null,

      // 音频多选功能
      selectedAudioIds: new Set(), // 使用Set存储选中的音频ID
      selectedCount: 0, // 辅助响应式变量，用于触发UI更新
      previewingAudioId: null, // 当前预览播放的音频ID
      selectedTargetCategory: 'background', // 用户选择的目标分类，默认为背景音乐

      // 新增分类数据
      newCategory: {
        key: '',
        name: '',
        description: '',
        icon: '🎵',
        subCategories: []
      },

      // 可选图标列表
      categoryIcons: [
        '🎵', '🎧', '🎭', '🎤', '🎹', '🎸', '🎺', '🎻', 
        '🎬', '🎮', '🎨', '🎪', '🎊', '🎉', '🔊', '📻',
        '💫', '⭐', '🌟', '✨', '🎯', '🎲', '🎰', '🎳',
        '🏆', '🎖️', '🏅', '🎗️', '🎀', '🎁', '🎂', '🍰'
      ],

        // 移动模式控制
        moveMode: false,
        movingAudioIndex: -1,
        movingCategoryKey: null,

      // 高亮显示的音频ID
      highlightedAudioId: null,

      // 搜索防抖定时器
      searchTimeout: null,

      // 音频播放器实例
      audioPlayer: null,

      // 音频播放状态
      isAudioPlaying: false,
      // 音频加载状态
      isAudioLoading: false,
      // 播放进度相关
      currentTime: 0,    // 当前播放时间（秒）
      totalDuration: 0,  // 总时长（秒）
      playProgress: 0,   // 播放进度百分比 (0-100)
      
      // 音频选择器数据
      availableAudios: [], // 当前筛选后的音频列表
      allAvailableAudios: [], // 所有可用音频（用于计算分类数量，不受分类筛选影响）
      searchText: "",
      selectedCategory: "",
      categoryOptions: [
        {
          label: "全部分类",
          value: "",
        },
      ],
    };
  },
  computed: {
    // 筛选后的可用音频列表
    filteredAvailableAudios() {
      let audios = this.availableAudios;

      // 过滤掉已经在播放列表中的音频
      audios = audios.filter(
        (audio) => !this.audioList.some((item) => item.id === audio.id)
      );

      // 搜索筛选 (只在前端搜索时进行，因为后端已经处理了搜索)
      // 注意：如果后端已经处理了搜索，这里可以删除
      // if (this.searchText) {
      //   const searchText = this.searchText.toLowerCase();
      //   audios = audios.filter(
      //     (audio) =>
      //       audio.name.toLowerCase().includes(searchText) ||
      //       (audio.category &&
      //         audio.category.toLowerCase().includes(searchText))
      //   );
      // }

      // 分类筛选已在后端处理，前端不再进行二次筛选

      return audios;
    },

    // 检查是否有任何音频在播放
    hasAnyPlaying() {
      return Object.values(this.categorizedAudioList).some((categoryAudios) =>
        (categoryAudios || []).some((audio) => audio.isPlaying)
      );
    },

    // 检查是否所有分类都已展开
    allCategoriesExpanded() {
      const categories = Object.keys(this.secondaryCategories);
      if (categories.length === 0) return false;
      return categories.every(categoryKey => {
        return this.secondaryCategories[categoryKey] && this.secondaryCategories[categoryKey].expanded !== false;
      });
    },

    // 获取当前正在播放的音频列表
    currentPlayingAudios() {
      const playingAudios = [];
      
      Object.keys(this.categorizedAudioList).forEach(categoryKey => {
        const categoryAudios = this.categorizedAudioList[categoryKey] || [];
        const categoryName = this.secondaryCategories[categoryKey]?.name;
        const categoryIcon = this.secondaryCategories[categoryKey]?.icon;
        const currentPlayingId = this.playingAudiosByCategory[categoryKey];
        
        // 检查分类播放器是否在播放
        if (currentPlayingId && this.audioPlayerInstances[categoryKey]) {
          const playingAudio = categoryAudios.find(audio => audio.id === currentPlayingId);
          if (playingAudio) {
            playingAudios.push({
              audio: playingAudio,
              categoryKey: categoryKey,
              categoryName: categoryName,
              categoryIcon: categoryIcon,
              // 添加进度信息
              progress: this.categoryPlayProgress[categoryKey] || {
                currentTime: 0,
                duration: 0,
                progress: 0
              },
              isMainPlayer: true // 标识这是分类播放器
            });
          }
        }
        
        // 检查单个音频播放状态（兼容旧的播放方式）
        categoryAudios.forEach(audio => {
          if (audio.isPlaying && audio.id !== currentPlayingId) {
            playingAudios.push({
              audio: audio,
              categoryKey: categoryKey,
              categoryName: categoryName,
              categoryIcon: categoryIcon,
              progress: {
                currentTime: 0,
                duration: audio.duration || 0,
                progress: 0
              },
              isMainPlayer: false // 标识这是单个音频播放
            });
          }
        });
      });
      
      return playingAudios;
    },

    // 是否全选
    isAllSelected() {
      // 使用 selectedCount 作为响应式依赖触发器
      this.selectedCount; // 触发响应式更新
      return this.filteredAvailableAudios.length > 0 && 
             this.selectedAudioIds.size === this.filteredAvailableAudios.length;
    },

    // 带数量的分类选项
    categoryOptionsWithCount() {
      // 基于当前房间文件夹数据显示选项，确保文件夹始终可见
      if (!this.categoryOptions) {
        return [];
      }

      return this.categoryOptions.map(option => {
        // 如果是"全部分类"选项
        if (option.value === '') {
          let totalCount = 0;
          if (this.allAvailableAudios && Array.isArray(this.allAvailableAudios)) {
            totalCount = this.allAvailableAudios.filter(
              audio => !this.audioList.some(item => item.id === audio.id)
            ).length;
          }
          return {
            ...option,
            label: totalCount > 0 ? `${option.label} (${totalCount})` : option.label
          };
        }

        // 计算分类下的音频数量，但始终显示文件夹选项
        let categoryCount = 0;
        
        // 只有在有音频数据时才计算数量，避免错误
        if (this.allAvailableAudios && Array.isArray(this.allAvailableAudios) && this.audioList) {
          if (option.value === 'root') {
            // 根目录：计算没有分类或分类为空的音频
            categoryCount = this.allAvailableAudios.filter(audio => {
              const notInPlaylist = !this.audioList.some(item => item.id === audio.id);
              const isRootCategory = !audio.category || audio.category === '' || audio.category === 'root';
              return notInPlaylist && isRootCategory;
            }).length;
          } else if (option.folderName) {
            // 文件夹分类：基于文件夹名称匹配音频的category字段
            categoryCount = this.allAvailableAudios.filter(audio => {
              const notInPlaylist = !this.audioList.some(item => item.id === audio.id);
              const matchesFolder = audio.category === option.folderName;
              return notInPlaylist && matchesFolder;
            }).length;
          } else {
            // 普通分类
            categoryCount = this.allAvailableAudios.filter(audio => {
              const notInPlaylist = !this.audioList.some(item => item.id === audio.id);
              const matchesCategory = audio.category === option.value;
              return notInPlaylist && matchesCategory;
            }).length;
          }
        }

        // 重要：文件夹选项始终显示，因为它们来自 zb_api_folders 表
        // 即使没有匹配的音频，文件夹依然存在并应该显示
        return {
          ...option,
          label: `${option.label} (${categoryCount})`
        };
      });
    },

  },
  onLoad(options) {
    console.log('🔧 页面加载，接收到的参数:', options);
    if (options.roomId) {
      this.currentRoom.id = options.roomId;
      console.log('🏠 从参数设置房间ID:', options.roomId);
    }
    console.log('🏠 当前房间信息:', this.currentRoom);
    
    // 设置导航栏标题为房间名称
    uni.setNavigationBarTitle({
      title: this.currentRoom.name + ' - 播放配置'
    });
    
    // 初始化音频播放器
    this.initAudioPlayer();
    console.log('🎵 开始调用loadData...');
    this.loadData(); // initVolumeData()将在loadData()中的适当时机调用
  },

  onUnload() {
    // 重置初始化标记
    this.isInitializing = false;
    this.isCategoryVolumeChanging = false;
    
    // 清空用户自定义音量记录
    this.customAudioVolumes.clear();
    this.customAudioVolumesTrigger++; // 触发Vue响应式更新
    
    // 页面销毁时清理音频播放器
    if (this.audioPlayer) {
      this.audioPlayer.destroy();
      this.audioPlayer = null;
    }
    
    // 清理所有分类的简单播放器
    Object.keys(this.audioPlayerInstances).forEach(categoryKey => {
      const playerInstance = this.audioPlayerInstances[categoryKey];
      if (playerInstance) {
        playerInstance.destroy();
      }
    });
    
    // 清理所有定时器
    this.globalAudioTimers.forEach(timer => {
      clearTimeout(timer);
    });
    this.globalAudioTimers = [];
    
    Object.keys(this.audioTimers).forEach(timerKey => {
      clearTimeout(this.audioTimers[timerKey]);
    });
    this.audioTimers = {};
    
    // 清理倒计时定时器
    Object.keys(this.countdownTimers).forEach(categoryKey => {
      clearInterval(this.countdownTimers[categoryKey]);
    });
    this.countdownTimers = {};
    
    // 清理下一首播放计划
    this.nextPlaySchedule = {};
    
    // 清理搜索定时器
    if (this.searchTimeout) {
      clearTimeout(this.searchTimeout);
      this.searchTimeout = null;
    }
    
    // 清理音量保存定时器
    Object.keys(this.volumeSaveTimers).forEach(audioId => {
      clearTimeout(this.volumeSaveTimers[audioId]);
    });
    this.volumeSaveTimers = {};
    
    Object.keys(this.categoryVolumeSaveTimers).forEach(categoryKey => {
      clearTimeout(this.categoryVolumeSaveTimers[categoryKey]);
    });
    this.categoryVolumeSaveTimers = {};
    
    this.audioPlayerInstances = {};
    this.playingAudiosByCategory = {};
    
    console.log('页面卸载，所有定时器、播放器和标记已清理');
  },
  methods: {
    // 音量控制相关方法
    
    // 获取分类音量
    getCategoryVolume(categoryKey) {
      if (this.categoryVolumes[categoryKey] !== undefined) {
        return this.categoryVolumes[categoryKey];
      }
      // 从分类配置中获取默认音量
      const categoryConfig = this.secondaryCategories[categoryKey];
      if (categoryConfig && categoryConfig.config && categoryConfig.config.volume !== undefined) {
        return categoryConfig.config.volume * 100; // 转换为百分比
      }
      return 100; // 默认100%
    },
    
    // 获取单个音频音量
    getAudioVolume(audioId) {
      if (this.audioVolumes[audioId] !== undefined) {
        return this.audioVolumes[audioId];
      }
      return 100; // 默认100%
    },
    
    // 同步分类下所有音频的音量
    syncCategoryAudioVolumes(categoryKey, volume) {
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      const audiosToSync = categoryAudios.filter(audio => !this.customAudioVolumes.has(audio.id));
      
      console.log(`🔄 同步分类 [${categoryKey}] 音量:`, {
        总音频数: categoryAudios.length,
        用户自定义音频数: categoryAudios.length - audiosToSync.length,
        需要同步音频数: audiosToSync.length,
        目标音量: `${volume}%`
      });
      
      audiosToSync.forEach(audio => {
        // 只同步那些没有被用户手动设置过的音频
        // 由于设置了 isCategoryVolumeChanging 标记，onAudioVolumeChange 不会触发保存
        this.$set(this.audioVolumes, audio.id, volume);
        console.log(`  📄 同步音频 [${audio.name}] 音量为 ${volume}%`);
      });
      
      if (audiosToSync.length < categoryAudios.length) {
        const customAudios = categoryAudios.filter(audio => this.customAudioVolumes.has(audio.id));
        console.log(`🔒 保持用户自定义音量的音频:`, customAudios.map(audio => 
          `${audio.name}(${this.audioVolumes[audio.id]}%)`).join(', '));
      }
      
      console.log(`✅ 分类 [${categoryKey}] 音量同步完成`);
    },
    
    // 处理音频播放结束后的逻辑
    handleAudioPlaybackEnded(categoryKey) {
      console.log(`🎵 音频播放结束处理 [${categoryKey}]`);
      
      const categoryConfig = this.secondaryCategories[categoryKey];
      if (!categoryConfig || !categoryConfig.config) {
        console.log(`⚠️ 分类配置不存在 [${categoryKey}]`);
        return;
      }
      
      const config = categoryConfig.config;
      console.log(`📋 分类配置 [${categoryKey}]:`, {
        autoPlay: config.autoPlay,
        playMode: config.playMode,
        intervalMin: config.intervalMin,
        intervalMax: config.intervalMax
      });
      
      // 检查是否启用了自动播放
      if (!config.autoPlay) {
        console.log(`🔇 分类 [${categoryKey}] 未启用自动播放`);
        return;
      }
      
      // 获取下一首要播放的音频（基于当前播放的音频ID）
      const currentPlayingId = this.playingAudiosByCategory[categoryKey];
      const nextAudio = this.getNextAudioToPlay(categoryKey, currentPlayingId);
      if (!nextAudio) {
        console.log(`🎵 分类 [${categoryKey}] 没有下一首音频可播放`);
        return;
      }
      
      // 计算播放间隔
      const intervalMin = config.intervalMin || 5;
      const intervalMax = config.intervalMax || 15;
      const playInterval = Math.floor(Math.random() * (intervalMax - intervalMin + 1)) + intervalMin;
      
      console.log(`⏰ 准备在 ${playInterval} 秒后播放下一首: ${nextAudio.name}`);
      
      // 设置下一首播放计划
      this.$set(this.nextPlaySchedule, categoryKey, {
        nextAudio: nextAudio,
        countdown: playInterval,
        totalInterval: playInterval
      });
      
      // 启动倒计时
      this.startPlayCountdown(categoryKey);
    },
    
    // 获取下一首要播放的音频
    getNextAudioToPlay(categoryKey, justPlayedAudioId = null) {
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      if (categoryAudios.length === 0) return null;
      
      const categoryConfig = this.secondaryCategories[categoryKey];
      if (!categoryConfig) return null;
      
      const playMode = categoryConfig.config.playMode || 'sequential';
      
      console.log(`🎯 获取下一首音频 [${categoryKey}] 播放模式: ${playMode}`, {
        justPlayedAudioId,
        总音频数: categoryAudios.length
      });
      
      if (playMode === 'random') {
        // 随机播放
        const randomIndex = Math.floor(Math.random() * categoryAudios.length);
        const nextAudio = categoryAudios[randomIndex];
        console.log(`🎲 随机选择第 ${randomIndex + 1} 首: ${nextAudio.name}`);
        return nextAudio;
      } else {
        // 顺序播放（默认）
        let currentIndex = -1;
        
        if (justPlayedAudioId) {
          currentIndex = categoryAudios.findIndex(audio => audio.id === justPlayedAudioId);
          console.log(`📋 找到刚播放完的音频索引: ${currentIndex}`);
        }
        
        const nextIndex = (currentIndex + 1) % categoryAudios.length;
        const nextAudio = categoryAudios[nextIndex];
        console.log(`📋 顺序播放第 ${nextIndex + 1} 首: ${nextAudio.name}`);
        return nextAudio;
      }
    },
    
    // 启动播放倒计时
    startPlayCountdown(categoryKey) {
      console.log(`⏰ 启动播放倒计时 [${categoryKey}]`);
      
      // 清理之前的倒计时
      this.clearCountdownTimer(categoryKey);
      
      const updateCountdown = () => {
        if (!this.nextPlaySchedule[categoryKey]) {
          console.log(`⚠️ 下一首播放计划不存在 [${categoryKey}]`);
          return;
        }
        
        this.nextPlaySchedule[categoryKey].countdown--;
        
        if (this.nextPlaySchedule[categoryKey].countdown <= 0) {
          // 倒计时结束，开始播放
          console.log(`🎵 倒计时结束，开始播放 [${categoryKey}]`);
          this.executeScheduledPlay(categoryKey);
        } else {
          console.log(`⏰ 倒计时 [${categoryKey}]: ${this.nextPlaySchedule[categoryKey].countdown} 秒`);
        }
      };
      
      // 每秒更新一次倒计时
      const timer = setInterval(updateCountdown, 1000);
      this.$set(this.countdownTimers, categoryKey, timer);
    },
    
    // 执行计划的播放
    async executeScheduledPlay(categoryKey) {
      console.log(`🎵 执行计划播放 [${categoryKey}]`);
      
      if (!this.nextPlaySchedule[categoryKey] || !this.nextPlaySchedule[categoryKey].nextAudio) {
        console.log(`⚠️ 没有计划的音频可播放 [${categoryKey}]`);
        return;
      }
      
      const nextAudio = this.nextPlaySchedule[categoryKey].nextAudio;
      
      // 清理倒计时和计划
      this.clearCountdownTimer(categoryKey);
      this.$delete(this.nextPlaySchedule, categoryKey);
      
      // 播放下一首音频
      try {
        await this.playSimpleAudio(nextAudio, categoryKey);
        console.log(`✅ 自动播放成功 [${categoryKey}]: ${nextAudio.name}`);
      } catch (error) {
        console.error(`❌ 自动播放失败 [${categoryKey}]:`, error);
      }
    },
    
    // 获取播放模式文本描述
    getPlayModeText(categoryKey) {
      const categoryConfig = this.secondaryCategories[categoryKey];
      if (!categoryConfig || !categoryConfig.config) {
        return '未配置';
      }
      
      const playMode = categoryConfig.config.playMode || 'sequential';
      const intervalMin = categoryConfig.config.intervalMin || 5;
      const intervalMax = categoryConfig.config.intervalMax || 15;
      
      const modeText = {
        'sequential': '顺序播放',
        'random': '随机播放',
        'loop': '循环播放',
        'manual': '手动播放'
      }[playMode] || '顺序播放';
      
      if (playMode === 'manual') {
        return modeText;
      }
      
      return `${modeText} • 间隔 ${intervalMin}-${intervalMax}s`;
    },
    
    // 检查音频是否被用户自定义过
    isAudioVolumeCustomized(audioId) {
      // 触发响应式依赖追踪
      this.customAudioVolumesTrigger;
      const isCustomized = this.customAudioVolumes.has(audioId);
      // 添加调试信息
      if (isCustomized) {
        console.log(`🔍 检查音频 [${audioId}] 是否自定义: 是`);
      }
      return isCustomized;
    },
    
    // 重置音频音量到分类默认值
    resetAudioVolumeToCategory(audioId, categoryKey) {
      const categoryVolume = this.getCategoryVolume(categoryKey);
      
      console.log(`🔄 重置音频 [${audioId}] 音量到分类默认值: ${categoryVolume}%`);
      
      // 从自定义音量集合中移除
      this.customAudioVolumes.delete(audioId);
      this.customAudioVolumesTrigger++; // 触发Vue响应式更新
      
      // 设置为分类音量
      this.$set(this.audioVolumes, audioId, categoryVolume);
      
      // 保存到数据库
      this.debounceSaveAudioVolume(audioId, categoryVolume);
      
      console.log(`✅ 音频 [${audioId}] 已重置为分类音量 ${categoryVolume}%`);
      console.log(`📋 重置后自定义音频列表:`, Array.from(this.customAudioVolumes));
      this.$message.success('音频音量已重置为分类默认值');
    },
    
    // 分类音量变化处理
    onCategoryVolumeChange(categoryKey, volume) {
      // 如果正在初始化，跳过所有分类音量变化操作
      if (this.isInitializing) {
        console.log(`🚫 初始化期间跳过分类音量变化: categoryKey=${categoryKey}, volume=${volume}`);
        return;
      }
      
      console.log(`🎺 用户调整分类音量 [${categoryKey}]: ${volume}%`);
      
      // 设置分类音量变化标记，防止同步音频时触发单个音频保存
      this.isCategoryVolumeChanging = true;
      
      this.$set(this.categoryVolumes, categoryKey, volume);
      
      // 同时更新分类配置中的音量
      if (this.secondaryCategories[categoryKey] && this.secondaryCategories[categoryKey].config) {
        this.$set(this.secondaryCategories[categoryKey].config, 'volume', volume / 100);
        console.log(`💾 已更新分类配置音量 [${categoryKey}]: ${volume / 100}`);
      }
      
      // 将该分类下所有音频的音量都设置为相同值
      this.syncCategoryAudioVolumes(categoryKey, volume);
      
      // 触发视觉更新
      this.updateCategoryAudioDisplay(categoryKey);
      
      // 如果该分类正在播放，立即应用音量
      this.$nextTick(() => {
        this.applyCategoryVolume(categoryKey);
      });

      // 使用防抖保存分类配置和所有音频音量
      this.debounceSaveCategoryVolume(categoryKey, volume);
      
      // 立即移除分类音量变化标记
      this.$nextTick(() => {
        this.isCategoryVolumeChanging = false;
        console.log(`✅ 分类音量变化完成 [${categoryKey}]`);
      });
    },

    // 防抖保存分类音量配置
    debounceSaveCategoryVolume(categoryKey, volume) {
      // 如果正在初始化，跳过保存操作
      if (this.isInitializing) {
        console.log(`🚫 初始化期间跳过分类音量保存: categoryKey=${categoryKey}, volume=${volume}`);
        return;
      }
      
      // 清除之前的定时器
      if (this.categoryVolumeSaveTimers[categoryKey]) {
        clearTimeout(this.categoryVolumeSaveTimers[categoryKey]);
      }
      
      // 设置新的防抖定时器，300ms后执行保存（减少等待时间）
      this.categoryVolumeSaveTimers[categoryKey] = setTimeout(() => {
        console.log(`⏰ 分类防抖触发，准备保存分类音量: categoryKey=${categoryKey}, volume=${volume}`);
        this.saveCategoryVolumeConfig(categoryKey, volume);
        // 清除定时器引用
        delete this.categoryVolumeSaveTimers[categoryKey];
      }, 300);
    },

    // 保存分类音量配置
    async saveCategoryVolumeConfig(categoryKey, volume) {
      // 双重检查：即使进入了这个方法，如果还在初始化就退出
      if (this.isInitializing) {
        console.warn(`🚫 saveCategoryVolumeConfig: 仍在初始化期间，跳过保存: categoryKey=${categoryKey}, volume=${volume}`);
        return;
      }
      
      try {
        console.log(`🔄 正在保存分类音量配置到数据库: categoryKey=${categoryKey}, volume=${volume}`);
        
        // 1. 保存分类配置的音量
        await updateRoomConfig({
          room_id: this.currentRoom.id,
          category_type: categoryKey,
          volume: volume / 100
        });
        console.log(`✅ 分类音量配置已保存: ${categoryKey} = ${volume}%`);

        // 2. 批量保存该分类下所有音频的音量（只保存没有被用户自定义的音频）
        const categoryAudios = this.categorizedAudioList[categoryKey] || [];
        const audiosToSave = categoryAudios.filter(audio => !this.customAudioVolumes.has(audio.id));
        
        if (audiosToSave.length > 0) {
          const volumeData = audiosToSave.map(audio => ({
            relation_id: audio.relationId,
            volume: volume / 100
          })).filter(item => item.relation_id); // 过滤掉没有 relationId 的项

          if (volumeData.length > 0) {
            await updateMultipleAudioVolumes(volumeData);
            console.log(`✅ 分类 [${categoryKey}] 下 ${volumeData.length} 个音频音量已批量保存（跳过了 ${categoryAudios.length - audiosToSave.length} 个用户自定义音频）`);
          }
        } else {
          console.log(`ℹ️ 分类 [${categoryKey}] 下所有音频都已被用户自定义，跳过批量保存`);
        }
      } catch (error) {
        console.error('保存分类音量配置失败:', error);
        this.$message.error('保存分类音量失败: ' + error);
      }
    },
    
    // 根据音频ID查找关系ID
    findRelationIdByAudioId(audioId) {
      console.log(`🔍 查找音频ID [${audioId}] 的关系ID`);
      
      for (const categoryKey of Object.keys(this.categorizedAudioList)) {
        const audios = this.categorizedAudioList[categoryKey] || [];
        console.log(`  - 检查分类 [${categoryKey}]: ${audios.length} 个音频`);
        
        const audio = audios.find(a => a.id === audioId);
        if (audio) {
          console.log(`  - 找到音频:`, audio);
          if (audio.relationId) {
            console.log(`✅ 找到关系ID: ${audio.relationId}`);
            return audio.relationId;
          } else {
            console.warn(`⚠️ 音频缺少relationId字段`);
          }
        }
      }
      
      console.error(`❌ 未找到音频ID [${audioId}] 的关系ID`);
      console.log(`📋 当前音频列表结构:`, this.categorizedAudioList);
      return null;
    },

    // 单个音频音量变化处理
    onAudioVolumeChange(audioId, volume) {
      console.log(`🔔 onAudioVolumeChange 被调用: audioId=${audioId}, volume=${volume}%`, {
        isInitializing: this.isInitializing,
        isCategoryVolumeChanging: this.isCategoryVolumeChanging,
        customAudioVolumes: Array.from(this.customAudioVolumes)
      });
      
      // 如果正在初始化，跳过所有音频音量变化操作
      if (this.isInitializing) {
        console.log(`🚫 初始化期间跳过音频音量变化: audioId=${audioId}, volume=${volume}`);
        return;
      }
      
      // 如果是分类音量变化引起的，只设置值不保存（避免重复保存）
      if (this.isCategoryVolumeChanging) {
        console.log(`🔄 分类音量变化期间设置音频音量: audioId=${audioId}, volume=${volume}%`);
        this.$set(this.audioVolumes, audioId, volume);
        return;
      }
      
      console.log(`🎚️ 用户手动调整音频音量: audioId=${audioId}, volume=${volume}%`);
      this.$set(this.audioVolumes, audioId, volume);
      
      // 记录这个音频已被用户手动设置过音量
      this.customAudioVolumes.add(audioId);
      this.customAudioVolumesTrigger++; // 触发Vue响应式更新
      console.log(`📝 记录音频 [${audioId}] 已被用户手动设置音量，将不再受分类音量影响`);
      console.log(`📋 当前自定义音频列表:`, Array.from(this.customAudioVolumes));
      
      // 如果该音频正在播放，立即应用音量
      this.applyAudioVolume(audioId);
      
      // 使用防抖保存音量到数据库
      this.debounceSaveAudioVolume(audioId, volume);
    },

    // 防抖保存音频音量
    debounceSaveAudioVolume(audioId, volume) {
      // 如果正在初始化，跳过保存操作
      if (this.isInitializing) {
        console.log(`🚫 初始化期间跳过音频音量保存: audioId=${audioId}, volume=${volume}`);
        return;
      }
      
      // 清除之前的定时器
      if (this.volumeSaveTimers[audioId]) {
        clearTimeout(this.volumeSaveTimers[audioId]);
      }
      
      // 设置新的防抖定时器，300ms后执行保存（减少等待时间）
      this.volumeSaveTimers[audioId] = setTimeout(() => {
        console.log(`⏰ 防抖触发，准备保存音频音量: audioId=${audioId}, volume=${volume}`);
        this.saveAudioVolume(audioId, volume);
        // 清除定时器引用
        delete this.volumeSaveTimers[audioId];
      }, 300);
    },

    // 保存音频音量到数据库
    async saveAudioVolume(audioId, volume) {
      // 双重检查：即使进入了这个方法，如果还在初始化就退出
      if (this.isInitializing) {
        console.warn(`🚫 saveAudioVolume: 仍在初始化期间，跳过保存: audioId=${audioId}, volume=${volume}`);
        return;
      }
      
      try {
        const relationId = this.findRelationIdByAudioId(audioId);
        if (!relationId) {
          console.warn('找不到音频的关系ID:', audioId);
          return;
        }

        // 将百分比转换为0-1的值
        const volumeValue = volume / 100;
        
        console.log(`🔄 正在保存音频音量到数据库: audioId=${audioId}, relationId=${relationId}, volume=${volumeValue}`);
        await updateAudioVolume(relationId, volumeValue);
        console.log(`✅ 音频音量已保存: audioId=${audioId}, relationId=${relationId}, volume=${volumeValue}`);
      } catch (error) {
        console.error('保存音频音量失败:', error);
        this.$message.error('保存音量失败: ' + error);
      }
    },
    
    // 应用分类音量
    applyCategoryVolume(categoryKey) {
      const playerInstance = this.audioPlayerInstances[categoryKey];
      const currentPlayingId = this.playingAudiosByCategory[categoryKey];
      
      console.log(`🔊 应用分类音量 [${categoryKey}]:`, {
        有播放器: !!playerInstance,
        有音频元素: !!(playerInstance && playerInstance.audioContext),
        当前播放的音频ID: currentPlayingId
      });
      
      if (playerInstance && playerInstance.audioContext && currentPlayingId) {
        // 直接使用音频的音量值（不再是分类音量×音频音量）
        const audioVolume = this.getAudioVolume(currentPlayingId) / 100;
        
        // 使用AudioPlayer的setVolume方法
        playerInstance.setVolume(audioVolume);
        
        console.log(`🔊 音量设置成功 [${categoryKey}]:`, {
          音频音量: `${Math.round(audioVolume * 100)}%`,
          实际设置值: audioVolume
        });
      } else {
        console.warn(`🔊 无法应用音量 [${categoryKey}]:`, {
          没有播放器: !playerInstance,
          没有音频元素: !playerInstance?.audioContext,
          没有播放中的音频: !currentPlayingId
        });
      }
    },
    
    // 应用单个音频音量
    applyAudioVolume(audioId) {
      // 找到该音频所在的分类
      for (const categoryKey of Object.keys(this.categorizedAudioList)) {
        const currentPlayingId = this.playingAudiosByCategory[categoryKey];
        if (currentPlayingId === audioId) {
          this.applyCategoryVolume(categoryKey);
          break;
        }
      }
    },
    
    // 格式化音量提示
    formatVolumeTooltip(value) {
      return value + '%';
    },
    
    // 初始化音量数据
    initVolumeData() {
      console.log('🔊 初始化音量数据');
      
      // 注意：不清空audioVolumes，因为它已经在convertApiAudioList中从数据库加载了
      // 只初始化分类音量设置
      if (!this.categoryVolumes) {
        this.categoryVolumes = {};
      }
      
      // 从分类配置中读取音量设置（不触发同步操作）
      Object.keys(this.secondaryCategories).forEach(categoryKey => {
        const categoryConfig = this.secondaryCategories[categoryKey];
        if (categoryConfig && categoryConfig.config && categoryConfig.config.volume !== undefined) {
          const categoryVolume = categoryConfig.config.volume * 100;
          // 直接设置分类音量，不触发同步
          this.categoryVolumes[categoryKey] = categoryVolume;
          console.log(`📊 读取分类音量配置 [${categoryKey}]: ${categoryVolume}%`);
        }
      });
      
      console.log('🔊 音量数据初始化完成');
      console.log('📊 音频音量配置状态:', {
        分类音量数量: Object.keys(this.categoryVolumes).length,
        音频音量数量: Object.keys(this.audioVolumes).length,
        音频音量示例: Object.keys(this.audioVolumes).slice(0, 3).map(id => `${id}: ${this.audioVolumes[id]}%`)
      });
    },
    
    // 更新分类下所有音频的显示效果
    updateCategoryAudioDisplay(categoryKey) {
      // 强制触发该分类下所有音频的视图更新
      // 这样音频音量显示会重新计算（包含分类音量的影响）
      this.$forceUpdate();
      
      // 添加短暂的视觉反馈，让用户知道哪些音频受到了影响
      this.highlightCategoryAudios(categoryKey);
      
      console.log(`🖼️ 更新分类 [${categoryKey}] 下所有音频的显示效果`);
    },
    
    // 高亮分类下的音频项
    highlightCategoryAudios(categoryKey) {
      // 简单的视觉反馈：短暂高亮该分类下的所有音频
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      categoryAudios.forEach(audio => {
        // 给每个音频添加一个短暂的高亮标记
        this.$set(audio, 'volumeUpdated', true);
      });
      
      // 1秒后移除高亮效果
      setTimeout(() => {
        categoryAudios.forEach(audio => {
          this.$set(audio, 'volumeUpdated', false);
        });
      }, 1000);
    },

    // 获取音频按钮图标
    getAudioButtonIcon(audio) {
      if (audio.isPlaying) {
        return 'el-icon-video-pause';
      }
      return 'el-icon-video-play';
    },

    // 获取音频按钮文本
    getAudioButtonText(audio) {
      return audio.isPlaying ? '暂停' : '播放';
    },

    // 格式化播放时间
    formatPlayTime(seconds) {
      if (!seconds || seconds < 0) return '00:00';
      const minutes = Math.floor(seconds / 60);
      const remainingSeconds = Math.floor(seconds % 60);
      return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
    },

    // 获取音频在整个列表中的序号
    getAudioIndex(targetAudio, targetCategoryKey) {
      let index = 0;
      
      // 按照分类键的顺序遍历
      const sortedCategoryKeys = Object.keys(this.categorizedAudioList).sort();
      
      for (const categoryKey of sortedCategoryKeys) {
        const categoryAudios = this.categorizedAudioList[categoryKey] || [];
        
        // 如果是目标分类，查找音频在该分类中的位置
        if (categoryKey === targetCategoryKey) {
          const audioIndex = categoryAudios.findIndex(audio => audio.id === targetAudio.id);
          if (audioIndex !== -1) {
            return index + audioIndex + 1; // +1 是因为序号从1开始
          }
          break; // 如果在目标分类中没找到，跳出循环
        } else {
          // 累计其他分类的音频数量
          index += categoryAudios.length;
        }
      }
      
      return 0; // 没找到时返回0
    },

    // 更新音频播放状态
    updatePlayingState() {
      // 遍历所有分类的音频，更新isPlaying状态
      Object.keys(this.categorizedAudioList).forEach(categoryKey => {
        const audios = this.categorizedAudioList[categoryKey] || [];
        const currentPlayingId = this.playingAudiosByCategory[categoryKey];
        const playerInstance = this.audioPlayerInstances[categoryKey];
        
        audios.forEach(audio => {
          audio.isPlaying = (audio.id === currentPlayingId && playerInstance?.isPlaying);
        });
      });
      
      // 强制更新视图
      this.$forceUpdate();
    },

    // 简单音频播放切换
    async simpleToggleAudioPlay(audioId, categoryKey) {
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      const audio = categoryAudios.find((item) => item.id === audioId);

      if (!audio) {
        console.warn('音频不存在:', audioId);
        return;
      }

      const currentPlayingId = this.playingAudiosByCategory[categoryKey];
      const playerInstance = this.audioPlayerInstances[categoryKey];

      // 如果当前音频正在播放，则暂停
      if (currentPlayingId === audioId && playerInstance?.isPlaying) {
        await this.pauseSimpleAudio(categoryKey);
        return;
      }

      // 播放新的音频
      await this.playSimpleAudio(audio, categoryKey);
    },

    // 播放音频（简单版本）
    async playSimpleAudio(audio, categoryKey) {
      try {
        // 为该分类创建播放器实例（如果不存在）
        if (!this.audioPlayerInstances[categoryKey]) {
          this.audioPlayerInstances[categoryKey] = new AudioPlayer();
          this.setupCategoryPlayerEvents(categoryKey);
        }

        const playerInstance = this.audioPlayerInstances[categoryKey];
        const currentPlayingId = this.playingAudiosByCategory[categoryKey];

        // 停止该分类当前播放的音频（同一分类内只能播放一个）
        if (currentPlayingId && playerInstance?.isPlaying) {
          playerInstance.stop();
        }

        console.log(`开始播放音频 [${categoryKey}]:`, audio.name, '路径:', audio.path || audio.file_path);

        // 确保音频对象有正确的file_path字段供AudioPlayer使用
        const audioForPlayer = {
          ...audio,
          file_path: audio.path || audio.file_path
        };

        // 加载并播放新音频
        const loadSuccess = await playerInstance.loadAudio(audioForPlayer);
        if (!loadSuccess) {
          console.error('音频加载失败:', audio.name);
          return;
        }

        const playSuccess = await playerInstance.play();
        if (playSuccess) {
          this.playingAudiosByCategory[categoryKey] = audio.id;
          
          // 应用音量设置
          this.applyCategoryVolume(categoryKey);
          
          this.updatePlayingState();
          console.log('播放成功:', audio.name);
        } else {
          console.warn('音频播放失败:', audio.name);
        }

      } catch (error) {
        console.error('播放音频失败:', error);
      }
    },

    // 暂停音频（简单版本）
    async pauseSimpleAudio(categoryKey) {
      try {
        const playerInstance = this.audioPlayerInstances[categoryKey];
        if (playerInstance?.isPlaying) {
          playerInstance.pause();
          this.updatePlayingState();
          console.log(`暂停播放 [${categoryKey}]`);
        }
      } catch (error) {
        console.error('暂停音频失败:', error);
      }
    },

    // 停止音频（简单版本）
    stopSimpleAudio(categoryKey) {
      try {
        const playerInstance = this.audioPlayerInstances[categoryKey];
        if (playerInstance) {
          playerInstance.stop();
          this.playingAudiosByCategory[categoryKey] = null;
          
          // 清理播放进度信息
          if (this.categoryPlayProgress[categoryKey]) {
            delete this.categoryPlayProgress[categoryKey];
          }
          
          this.updatePlayingState();
          console.log(`停止播放 [${categoryKey}]`);
        }
      } catch (error) {
        console.error('停止音频失败:', error);
      }
    },

    // 为分类播放器设置事件监听
    setupCategoryPlayerEvents(categoryKey) {
      const playerInstance = this.audioPlayerInstances[categoryKey];
      if (!playerInstance) return;

      playerInstance.onPlay(() => {
        console.log(`简单播放器 [${categoryKey}]：音频开始播放`);
        this.updatePlayingState();
      });

      playerInstance.onPause(() => {
        console.log(`简单播放器 [${categoryKey}]：音频暂停播放`);
        this.updatePlayingState();
      });

      // 播放进度更新监听
      playerInstance.onTimeUpdate((currentTime, duration) => {
        // 使用 Vue.set 或 this.$set 确保响应式更新
        if (!this.categoryPlayProgress[categoryKey]) {
          this.$set(this.categoryPlayProgress, categoryKey, {});
        }
        
        const progressData = {
          currentTime: currentTime,
          duration: duration,
          progress: duration > 0 ? (currentTime / duration) * 100 : 0
        };
        
        // 更新进度数据
        this.$set(this.categoryPlayProgress, categoryKey, progressData);
        
        console.log(`更新播放进度 [${categoryKey}]:`, progressData.progress.toFixed(1) + '%');
      });

      // 音频加载完成监听
      playerInstance.onLoaded((duration) => {
        const progressData = {
          currentTime: 0,
          duration: duration,
          progress: 0
        };
        
        // 使用 Vue.set 确保响应式更新
        this.$set(this.categoryPlayProgress, categoryKey, progressData);
        
        console.log(`音频加载完成 [${categoryKey}]:`, '时长:', duration + 's');
      });

      playerInstance.onEnded(() => {
        console.log(`简单播放器 [${categoryKey}]：音频播放结束`);
        
        // 在清空播放状态之前先处理自动播放逻辑
        this.handleAudioPlaybackEnded(categoryKey);
        
        // 然后清空播放状态
        this.playingAudiosByCategory[categoryKey] = null;
        this.updatePlayingState();
      });

      playerInstance.onError((error) => {
        console.error(`简单播放器 [${categoryKey}]：播放错误`, error);
        // this.$message.error('播放失败：' + error);
        this.playingAudiosByCategory[categoryKey] = null;
        this.updatePlayingState();
      });
    },

    // 初始化音频播放器
    initAudioPlayer() {
      this.audioPlayer = new AudioPlayer();
      
      // 简单播放器实例现在按需创建，不在这里初始化
      
      // 设置音频播放器事件监听
      this.audioPlayer.onPlay(() => {
        console.log('音频开始播放');
        // 状态由点击事件直接管理，这里只记录日志
      });

      this.audioPlayer.onPause(() => {
        console.log('音频暂停播放');
        // 状态由点击事件直接管理，这里只记录日志
      });

      // 播放进度更新监听
      this.audioPlayer.onTimeUpdate((currentTime, duration) => {
        this.currentTime = currentTime;
        this.totalDuration = duration;
        this.playProgress = duration > 0 ? (currentTime / duration) * 100 : 0;
      });

      // 音频加载完成监听
      this.audioPlayer.onLoaded((duration) => {
        this.totalDuration = duration;
        this.currentTime = 0;
        this.playProgress = 0;
      });

      this.audioPlayer.onEnded(() => {
        console.log('音频播放结束');
        // 播放结束时重置当前音频的播放状态
        this.availableAudios.forEach(audio => {
          if (audio.id === this.previewingAudioId) {
            audio.isPlaying = false;
          }
        });
        this.previewingAudioId = null;
        // 重置播放进度
        this.currentTime = 0;
        this.totalDuration = 0;
        this.playProgress = 0;
        this.$forceUpdate();
      });

      this.audioPlayer.onError((error) => {
        console.error('音频播放错误:', error);
        // 播放错误时重置当前音频的播放状态
        this.availableAudios.forEach(audio => {
          if (audio.id === this.previewingAudioId) {
            audio.isPlaying = false;
          }
        });
        this.previewingAudioId = null;
        // 重置播放进度
        this.currentTime = 0;
        this.totalDuration = 0;
        this.playProgress = 0;
        this.$forceUpdate();
      });
    },

    // 加载数据
    async loadData() {
      console.log('🚀 开始加载数据，当前房间ID:', this.currentRoom.id);
      this.loading = true;
      
      // 设置初始化标记，防止在整个数据加载过程中触发接口调用
      this.isInitializing = true;
      
      try {
        // 加载房间音频配置
        console.log('📋 开始加载房间音频配置...');
        await this.loadRoomConfigs();
        
        // 加载房间音频列表
        console.log('🎵 开始加载房间音频列表...');
        await this.loadRoomAudios();
        
        // 不需要再调用 initAudioList()，因为 loadRoomAudios() 已经处理了数据组织
        // this.initAudioList();
        
        // 数据加载完成后重新初始化音量数据（此时音频数据已包含音量信息）
        this.initVolumeData();
        
        console.log('✅ 数据加载完成');
      } catch (error) {
        console.error("❌ 加载数据失败:", error);
        this.$message.error("加载失败");
      } finally {
        this.loading = false;
        // 延迟移除初始化标记，确保所有响应式更新都完成
        this.$nextTick(() => {
          setTimeout(() => {
            this.isInitializing = false;
            console.log('🔓 初始化标记已移除，音量变化将正常保存到数据库');
          }, 100); // 延迟100ms确保所有更新完成
        });
      }
    },

    // 加载房间音频配置
    async loadRoomConfigs() {
      try {
        console.log('🔍 正在请求房间配置，房间ID:', this.currentRoom.id);
        const configs = await getRoomConfigs(this.currentRoom.id);
        console.log('📨 收到房间配置数据:', configs);
        
        // 处理所有从数据库加载的分类配置
        Object.keys(configs).forEach(categoryType => {
          const config = configs[categoryType];
          
          // 获取分类显示信息，优先使用数据库中的自定义信息
          let categoryData;
          
          if (config.category_name || config.description || config.icon) {
            // 这是一个自定义分类或有自定义信息的分类
            categoryData = {
              name: config.category_name || this.getDefaultCategoryName(categoryType),
              description: config.description || this.getDefaultCategoryDescription(categoryType),
              icon: config.icon || this.getDefaultCategoryIcon(categoryType),
              subCategories: [config.category_name || this.getDefaultCategoryName(categoryType)],
              config: {
                playMode: config.play_mode,
                intervalMin: config.interval_min,
                intervalMax: config.interval_max,
                autoPlay: config.auto_play === 1,
                maxConcurrent: config.max_concurrent || 1,
                volume: config.volume || 1.0,
                randomFragment: config.random_fragment === 1,
                fragmentMinDuration: config.fragment_min_duration || 3,
                fragmentMaxDuration: config.fragment_max_duration || 8,
                fragmentProbability: config.fragment_probability || 35,
                fragmentMinAudioLength: config.fragment_min_audio_length || 15,
                fragmentStartStrategy: config.fragment_start_strategy || 'avoid_start'
              },
              expanded: config.is_expanded === 1,
            };
          } else {
            // 这是默认分类，使用系统默认配置
            categoryData = {
              name: this.getDefaultCategoryName(categoryType),
              description: this.getDefaultCategoryDescription(categoryType),
              icon: this.getDefaultCategoryIcon(categoryType),
              subCategories: this.getDefaultCategorySubCategories(categoryType),
              config: {
                playMode: config.play_mode,
                intervalMin: config.interval_min,
                intervalMax: config.interval_max,
                autoPlay: config.auto_play === 1,
                maxConcurrent: config.max_concurrent || 1,
                volume: config.volume || 1.0,
                randomFragment: config.random_fragment === 1,
                fragmentMinDuration: config.fragment_min_duration || 3,
                fragmentMaxDuration: config.fragment_max_duration || 8,
                fragmentProbability: config.fragment_probability || 35,
                fragmentMinAudioLength: config.fragment_min_audio_length || 15,
                fragmentStartStrategy: config.fragment_start_strategy || 'avoid_start'
              },
              expanded: config.is_expanded === 1,
            };
          }
          
          // 添加到分类列表
          this.$set(this.secondaryCategories, categoryType, categoryData);
          
          // 初始化分类音频列表
          if (!this.categorizedAudioList[categoryType]) {
            this.$set(this.categorizedAudioList, categoryType, []);
          }
          
          // 添加到分类选择器选项
          const categoryName = categoryData.name;
          const existingOption = this.categoryOptions.find(opt => opt.value === categoryName);
          if (!existingOption) {
            this.categoryOptions.push({
              label: categoryName,
              value: categoryName
            });
          }
          
          console.log(`加载分类: ${categoryType} - ${categoryName}`);
        });
        
        console.log('房间配置加载成功:', configs);
        console.log('当前分类列表:', this.secondaryCategories);
      } catch (error) {
        console.error('加载房间配置失败:', error);
        // 使用默认配置
      }
    },

    // 加载房间音频列表
    async loadRoomAudios() {
      try {
        const audioData = await getRoomAudios(this.currentRoom.id);
        
        // 完全重建分类音频列表对象
        const newCategorizedAudioList = {};
        
        // 为所有已知分类初始化音频列表
        Object.keys(this.secondaryCategories).forEach(categoryKey => {
          const convertedList = this.convertApiAudioList(audioData[categoryKey] || []);
          newCategorizedAudioList[categoryKey] = convertedList;
        });
        
        // 一次性替换整个对象以触发响应式更新
        this.categorizedAudioList = newCategorizedAudioList;
        
        // 合并所有音频到 audioList 用于兼容现有逻辑
        this.audioList = [];
        Object.keys(this.categorizedAudioList).forEach(categoryKey => {
          this.audioList.push(...(this.categorizedAudioList[categoryKey] || []));
        });
        
        console.log('房间音频列表加载成功:', audioData);
      } catch (error) {
        console.error('加载房间音频列表失败:', error);
        this.$message.warning('加载房间音频配置失败，请检查网络连接');
        
        // 不要清空现有数据，保持用户已添加的音频
        // this.initAudioList(); 
      }
    },

    // 转换API音频数据格式
    convertApiAudioList(apiAudioList) {
      return apiAudioList.map(audio => {
        const audioId = audio.audio_id.toString();
        const volumePercent = (audio.volume || 1.0) * 100; // 将0-1转换为0-100%
        
        // 直接设置音频音量，避免触发响应式更新
        // 在初始化期间，直接设置属性值而不使用$set
        this.audioVolumes[audioId] = volumePercent;
        
        console.log(`📊 从数据库加载音频音量: ${audio.display_name || audio.name} [${audioId}] = ${volumePercent}%`);
        
        return {
          id: audioId,
          relationId: audio.relation_id,
          name: audio.display_name || audio.name,
          category: audio.sub_category || '未分类',
          duration: audio.duration || 0,
          path: audio.file_path,
          secondaryCategory: audio.category_type,
          isPlaying: false,
          volume: volumePercent
        };
      });
    },

    // 加载文件夹目录
    async loadFolderCategories() {
      this.categoriesLoading = true;
      try {
        console.log('开始加载房间文件夹目录:', this.currentRoom.id);
        
        // 保存当前选择
        const currentSelection = this.selectedCategory;
        
        const folders = await audioAPI.getAllFolders(this.currentRoom.id);
        this.folderList = folders || [];
        
        // 调试：打印实际接收到的文件夹数据
        console.log('🔍 getAllFolders API 返回的文件夹数据:', {
          roomId: this.currentRoom.id,
          foldersCount: folders ? folders.length : 0,
          folders: folders
        });
        
        // 构建分类选择器选项
        this.categoryOptions = [
          {
            label: "全部分类",
            value: "",
          }
        ];
        
        // 添加根目录选项
        this.categoryOptions.push({
          label: "📁 根目录",
          value: "root"
        });
        
        // 将文件夹转换为分类选项
        console.log('🔄 开始将文件夹转换为分类选项...');
        folders.forEach((folder, index) => {
          console.log(`📂 处理第${index + 1}个文件夹:`, folder);
          this.categoryOptions.push({
            label: `📁 ${folder.name}`,
            value: folder.id.toString(),
            folderName: folder.name,
            parentId: folder.parent_id
          });
        });
        
        console.log('✅ 分类选项构建完成，总数:', this.categoryOptions.length);
        console.log('📋 完整分类选项:', this.categoryOptions);
        
        // 检查之前的选择是否仍然有效
        const isValidSelection = this.categoryOptions.some(option => option.value === currentSelection);
        if (!isValidSelection && currentSelection !== "") {
          // 如果之前的选择无效且不是空值，重置为"全部分类"
          console.log('之前的选择无效，重置为全部分类:', currentSelection);
          this.selectedCategory = "";
        } else if (isValidSelection) {
          // 如果选择仍然有效，保持当前选择
          this.selectedCategory = currentSelection;
          console.log('保持当前选择:', currentSelection);
        }
        
        console.log('📁 文件夹目录加载成功, 数量:', folders.length);
        console.log('🎯 当前选择:', this.selectedCategory);
      } catch (error) {
        console.error('加载文件夹目录失败:', error);
        this.$message.error('加载文件夹目录失败: ' + error.message);
        // 出错时重置选择
        this.selectedCategory = "";
      } finally {
        this.categoriesLoading = false;
      }
    },

    // 加载可选音频列表
    async loadAvailableAudios() {
      this.availableAudiosLoading = true;
      try {
        // 获取已添加的音频ID列表，用于排除
        const excludeIds = this.audioList.map(audio => audio.id);
        
        // 首先获取全量音频数据（用于计算分类数量）
        if (!this.selectedCategory || this.selectedCategory === '') {
          // 如果没有选择分类，直接获取全量数据
          const allAudios = await audioAPI.getAvailableAudios(
            this.currentRoom.id,
            '', // 不传搜索条件
            '', // 不传分类条件
            excludeIds
          );
          
          this.allAvailableAudios = allAudios.map(audio => ({
            id: audio.id.toString(),
            name: audio.name,
            category: audio.category,
            duration: audio.duration || 0,
            file_path: audio.file_path,
            isPlaying: false,
            path: audio.file_path,
            size: audio.file_size,
            format: audio.format
          }));
          
          // 全部分类时，当前列表就是全量数据
          this.availableAudios = [...this.allAvailableAudios];
        } else {
          // 如果已有全量数据，不需要重新获取
          if (this.allAvailableAudios.length === 0) {
            const allAudios = await audioAPI.getAvailableAudios(
              this.currentRoom.id,
              '', // 不传搜索条件
              '', // 不传分类条件
              excludeIds
            );
            
            this.allAvailableAudios = allAudios.map(audio => ({
              id: audio.id.toString(),
              name: audio.name,
              category: audio.category,
              duration: audio.duration || 0,
              file_path: audio.file_path,
              isPlaying: false,
              path: audio.file_path,
              size: audio.file_size,
              format: audio.format
            }));
          }
          
          // 获取筛选后的音频数据
          // 根据分类类型构建查询参数
          let categoryParam = this.selectedCategory;
          if (this.selectedCategory === 'root') {
            categoryParam = 'root'; // 根目录
          } else if (this.selectedCategory && this.selectedCategory !== '') {
            // 检查是否是文件夹ID
            const selectedOption = this.categoryOptions.find(opt => opt.value === this.selectedCategory);
            if (selectedOption && selectedOption.folderName) {
              categoryParam = `folder_${this.selectedCategory}`; // 标识为文件夹筛选
            }
          }

          const filteredAudios = await audioAPI.getAvailableAudios(
            this.currentRoom.id,
            this.searchText,
            categoryParam,
            excludeIds
          );
          
          // 转换数据格式
          this.availableAudios = filteredAudios.map(audio => ({
            id: audio.id.toString(),
            name: audio.name,
            category: audio.category,
            duration: audio.duration || 0,
            file_path: audio.file_path, // AudioPlayer需要这个字段
            isPlaying: false, // 添加播放状态
            path: audio.file_path,      // 保持兼容性
            size: audio.file_size,
            format: audio.format
          }));
        }
        
        console.log(`加载音频列表成功，全量 ${this.allAvailableAudios.length} 个，当前显示 ${this.availableAudios.length} 个可选音频`);
      } catch (error) {
        console.error('加载可选音频列表失败:', error);
        this.$message.error('加载可选音频失败: ' + error);
        this.availableAudios = [];
        this.allAvailableAudios = [];
      } finally {
        this.availableAudiosLoading = false;
      }
    },

    // 更新房间配置
    async updateCategoryConfig(categoryType, configData) {
      console.log('🚀 updateCategoryConfig API调用开始:', categoryType, configData);
      try {
        const updateData = {
          room_id: this.currentRoom.id,
          category_type: categoryType,
          play_mode: configData.playMode,
          interval_min: configData.intervalMin,
          interval_max: configData.intervalMax,
          auto_play: configData.autoPlay ? 1 : 0,
          volume: configData.volume || 1.0,
          is_expanded: this.secondaryCategories[categoryType].expanded ? 1 : 0,
          // 添加随机片段播放相关字段
          max_concurrent: configData.maxConcurrent || 1,
          random_fragment: configData.randomFragment ? 1 : 0,
          fragment_min_duration: configData.fragmentMinDuration || 3,
          fragment_max_duration: configData.fragmentMaxDuration || 8,
          fragment_probability: configData.fragmentProbability || 35,
          fragment_min_audio_length: configData.fragmentMinAudioLength || 15,
          fragment_start_strategy: configData.fragmentStartStrategy || 'avoid_start'
        };

        console.log('📡 即将发送API请求，数据:', updateData);
        await updateRoomConfig(updateData);
        console.log('✅ API请求成功完成!');
        
        this.$message.success('配置更新成功');
        console.log('配置更新成功:', categoryType, configData);
      } catch (error) {
        console.error('❌ 更新配置失败:', error);
        this.$message.error('配置更新失败: ' + error);
      }
    },

    // 添加音频到房间
    async addAudioToCategory(audioId, categoryType, subCategory = null) {
      try {
        const result = await addAudioToRoom({
          room_id: this.currentRoom.id,
          audio_id: audioId,
          category_type: categoryType,
          sub_category: subCategory
        });
        
        // 重新加载音频列表
        await this.loadRoomAudios();
        this.$message.success('音频添加成功');
        
        return result.relation_id;
      } catch (error) {
        console.error('添加音频失败:', error);
        this.$message.error('添加音频失败: ' + error);
        throw error;
      }
    },

    // 从房间移除音频
    async removeAudioFromCategory(relationId) {
      try {
        await removeAudioFromRoom(relationId);
        
        // 重新加载音频列表
        await this.loadRoomAudios();
        this.$message.success('音频移除成功');
      } catch (error) {
        console.error('移除音频失败:', error);
        this.$message.error('移除音频失败: ' + error);
        throw error;
      }
    },

    // 初始化音频列表
    initAudioList() {
      this.audioList = [...this.rawAudioList];
      this.categorizeAudioList();
    },

    // 将音频按二级分类组织
    categorizeAudioList() {
      // 清空分类列表，但保持所有已知分类
      this.categorizedAudioList = {};
      Object.keys(this.secondaryCategories).forEach(categoryKey => {
        this.categorizedAudioList[categoryKey] = [];
      });

      this.audioList.forEach((audio) => {
        const category = this.getSecondaryCategory(audio.category);
        if (this.categorizedAudioList[category]) {
          this.categorizedAudioList[category].push({
            ...audio,
            secondaryCategory: category,
            isPlaying: false, // 添加播放状态
          });
        } else {
          // 如果分类不存在，添加到other分类
          if (this.categorizedAudioList.other) {
            this.categorizedAudioList.other.push({
              ...audio,
              secondaryCategory: 'other',
              isPlaying: false,
            });
          }
        }
      });
    },

    // 根据一级分类获取二级分类
    getSecondaryCategory(primaryCategory) {
      if (!primaryCategory) return "other";

      for (const [key, categoryInfo] of Object.entries(
        this.secondaryCategories
      )) {
        if (categoryInfo.subCategories.includes(primaryCategory)) {
          return key;
        }
      }
      
      // 如果没找到匹配的分类，检查是否与分类名称完全匹配
      for (const [key, categoryInfo] of Object.entries(
        this.secondaryCategories
      )) {
        if (categoryInfo.name === primaryCategory) {
          return key;
        }
      }
      
      return "other";
    },

    // 切换分类展开状态
    toggleCategoryExpanded(categoryKey) {
      this.secondaryCategories[categoryKey].expanded =
        !this.secondaryCategories[categoryKey].expanded;
      
      console.log(`分类 ${categoryKey} 展开状态已切换为:`, this.secondaryCategories[categoryKey].expanded);
      // 注意：展开状态的更改只在本地生效，需要点击"保存配置"才会同步到服务器
    },

    // 显示音频选择器
    async showAudioPicker(defaultCategory = 'background') {
      this.audioPickerVisible = true;
      // 重置选择状态
      this.selectedAudioIds.clear();
      this.selectedCount = 0;
      
      // 设置默认选中的分类
      this.selectedTargetCategory = defaultCategory;
      
      // 先加载文件夹目录，再加载音频列表
      try {
        // 每次都重新加载文件夹目录，确保数据是最新的
        console.log('🔄 音频选择弹窗打开，重新加载文件夹目录...');
        await this.loadFolderCategories();
        
        // 然后加载音频列表
        await this.loadAvailableAudios();
      } catch (error) {
        console.error('加载数据失败:', error);
      }
    },

    // 处理关闭音频选择器
    handleCloseAudioPicker() {
      console.log('处理关闭音频选择器按钮被点击');
      this.closeAudioPicker();
    },

    // 关闭音频选择器
    closeAudioPicker() {
      console.log('关闭音频选择器被调用');
      // 停止任何正在预览的音频
      if (this.previewingAudioId) {
        this.stopPreviewAudio();
      }
      this.audioPickerVisible = false;
      this.searchText = "";
      this.selectedCategory = "";
      // 清空选择状态
      this.selectedAudioIds.clear();
      this.selectedCount = 0;
      // 重置播放状态
      this.isAudioPlaying = false;
      this.isAudioLoading = false;
      this.availableAudiosLoading = false;
      this.categoriesLoading = false;
      // 重置音频数据
      this.availableAudios = [];
      this.allAvailableAudios = [];
      
      // 清除搜索防抖定时器
      if (this.searchTimeout) {
        clearTimeout(this.searchTimeout);
        this.searchTimeout = null;
      }
    },

    // 切换音频选择状态
    toggleAudioSelection(audioId) {
      if (this.selectedAudioIds.has(audioId)) {
        this.selectedAudioIds.delete(audioId);
      } else {
        this.selectedAudioIds.add(audioId);
      }
      // 更新选择计数，触发响应式更新
      this.selectedCount = this.selectedAudioIds.size;
    },

    // 切换全选状态
    toggleSelectAll() {
      if (this.isAllSelected) {
        // 取消全选
        this.selectedAudioIds.clear();
      } else {
        // 全选
        this.selectedAudioIds.clear();
        this.filteredAvailableAudios.forEach(audio => {
          this.selectedAudioIds.add(audio.id);
        });
      }
      // 更新选择计数，触发响应式更新
      this.selectedCount = this.selectedAudioIds.size;
    },

    // 清空选择
    clearSelection() {
      this.selectedAudioIds.clear();
      this.selectedCount = 0;
    },

    // 批量添加选中的音频
    async addSelectedAudios() {
      if (this.selectedAudioIds.size === 0) {
        this.$message.warning("请先选择音频");
        return;
      }

      // 设置加载状态
      this.addingAudios = true;

      // 获取选中的音频ID列表
      const selectedAudioIds = Array.from(this.selectedAudioIds);
      
      try {
        // 使用用户选择的分类
        const targetCategory = this.selectedTargetCategory;
        const categoryName = this.secondaryCategories[targetCategory]?.name || '未知分类';
        
        // 调用批量添加接口
        const result = await addMultipleAudiosToRoom({
          room_id: this.currentRoom.id,
          audio_ids: selectedAudioIds,
          category_type: targetCategory,
          sub_category: categoryName
        });

        // 显示结果提示
        this.$message({
          message: result.msg || '批量添加完成',
          type: 'success',
          duration: 2000
        });

        console.log('批量添加结果:', result.data);

        // 重新加载房间音频列表以显示最新数据
        await this.loadRoomAudios();

        // 清空选择并关闭弹窗
        this.selectedAudioIds.clear();
        this.selectedCount = 0;
        this.closeAudioPicker();

      } catch (error) {
        console.error('批量添加音频失败:', error);
        this.$message.error('批量添加失败: ' + error);
        
        // 不要在API失败时进行回退添加，避免数据不一致
        // 提示用户检查网络连接后重试
        this.$message({
          message: '网络请求失败，请检查连接后重新尝试',
          type: 'warning',
          duration: 3000
        });
      } finally {
        // 重置加载状态
        this.addingAudios = false;
      }
    },

    // 添加音频到播放列表
    async addAudioToList(audio) {
      // 检查是否已存在
      if (this.audioList.some((item) => item.id === audio.id)) {
        this.$message({
          message: "音频已存在",
          type: 'warning'
        });
        return;
      }

      try {
        const secondaryCategory = this.getSecondaryCategory(audio.category);
        const categoryName = this.secondaryCategories[secondaryCategory].name;
        
        // 调用API添加音频到房间
        const relationId = await this.addAudioToCategory(
          audio.id, 
          secondaryCategory, 
          audio.category
        );

        console.log(
          `添加完成：${audio.name}，relation_id: ${relationId}`
        );

        this.$message.success(`已添加到"${categoryName}": ${audio.name}`);

        // 添加成功后关闭弹窗
        this.closeAudioPicker();
      } catch (error) {
        console.error('添加音频失败:', error);
        this.$message.error('添加音频失败，请检查网络连接后重试');
      }
    },

    // 删除音频 (支持分类删除)
    removeAudio(audioId, categoryKey = null) {
      let audio;

      if (categoryKey) {
        // 从分类列表中查找
        audio = (this.categorizedAudioList[categoryKey] || []).find(
          (item) => item.id === audioId
        );
      } else {
        // 从总列表中查找
        audio = this.audioList.find((item) => item.id === audioId);
      }

      if (!audio) {
        this.$message.error("音频不存在");
        return;
      }

      uni.showModal({
        title: "确认删除",
        content: `确定要删除音频"${audio.name}"吗？`,
        success: async (res) => {
          if (res.confirm) {
            // 设置删除状态
            this.removingAudioIds.add(audioId);
            
            try {
              // 调用API删除音频关联
              if (audio.relationId) {
                await this.removeAudioFromCategory(audio.relationId);
                console.log(`删除完成：${audio.name}`);
              } else {
                // 如果没有relationId，则为静态数据，使用原逻辑
                const audioIndex = this.audioList.findIndex((item) => item.id === audioId);
                if (audioIndex >= 0) {
                  const newArray = [...this.audioList];
                  newArray.splice(audioIndex, 1);
                  this.audioList = newArray;
                  this.categorizeAudioList();
                  this.$message.success("音频已删除");
                }
              }
            } catch (error) {
              console.error('删除音频失败:', error);
            } finally {
              // 移除删除状态
              this.removingAudioIds.delete(audioId);
            }
          }
        },
      });
    },

    // 分类随机排序
    randomSortCategory(categoryKey) {
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      if (categoryAudios.length <= 1) return;

      // Fisher-Yates 洗牌算法
      const shuffledArray = [...categoryAudios];
      for (let i = shuffledArray.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        const temp = shuffledArray[i];
        shuffledArray[i] = shuffledArray[j];
        shuffledArray[j] = temp;
      }

      // 更新分类音频列表
      this.categorizedAudioList[categoryKey] = shuffledArray;

      // 同步更新总列表
      this.syncAudioListFromCategories();

      const categoryName = this.secondaryCategories[categoryKey].name;
      this.$message.success(`${categoryName} 已随机排序`);

      console.log(`${categoryName} 随机排序完成`);
    },

    // 分类按时长排序
    sortCategoryByDuration(categoryKey) {
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      if (categoryAudios.length <= 1) return;

      // 按时长排序（短到长）
      const sortedArray = [...categoryAudios];
      sortedArray.sort((a, b) => a.duration - b.duration);

      // 更新分类音频列表
      this.categorizedAudioList[categoryKey] = sortedArray;

      // 同步更新总列表
      this.syncAudioListFromCategories();

      const categoryName = this.secondaryCategories[categoryKey].name;
      this.$message.success(`${categoryName} 已按时长排序`);

      console.log(`${categoryName} 按时长排序完成`);
    },

    // 分类按名称排序
    sortCategoryByName(categoryKey) {
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      if (categoryAudios.length <= 1) return;

      // 按名称排序（A-Z）
      const sortedArray = [...categoryAudios];
      sortedArray.sort((a, b) => a.name.localeCompare(b.name));

      // 更新分类音频列表
      this.categorizedAudioList[categoryKey] = sortedArray;

      // 同步更新总列表
      this.syncAudioListFromCategories();

      const categoryName = this.secondaryCategories[categoryKey].name;
      this.$message.success(`${categoryName} 已按名称排序`);

      console.log(`${categoryName} 按名称排序完成`);
    },

    // 同步分类列表到总列表
    syncAudioListFromCategories() {
      const newAudioList = [];

      // 按分类顺序重组总列表
      Object.keys(this.secondaryCategories).forEach((categoryKey) => {
        newAudioList.push(...(this.categorizedAudioList[categoryKey] || []));
      });

      // 更新总列表
      this.audioList = newAudioList;

      // 强制更新视图
      this.$forceUpdate();
    },


    // 进入分类内移动模式
    enterCategoryMoveMode(categoryKey, index) {
      this.moveMode = true;
      this.movingAudioIndex = index;
      this.movingCategoryKey = categoryKey;
      
      const audio = (this.categorizedAudioList[categoryKey] || [])[index];
      const categoryName = this.secondaryCategories[categoryKey].name;
      
      // 强制更新视图以显示移动状态
      this.$forceUpdate();
      
      this.$message.info(`正在移动"${audio.name}"，请点击➕插入按钮选择位置`);
    },

    // 插入到指定位置
    insertAtPosition(categoryKey, targetIndex) {
      if (!this.moveMode || this.movingAudioIndex === -1 || this.movingCategoryKey !== categoryKey) {
        return;
      }
      
      const movingIndex = this.movingAudioIndex;
      const categoryAudios = [...this.categorizedAudioList[categoryKey]];
      const movingItem = categoryAudios[movingIndex];
      
      // 如果目标位置就是当前位置或紧邻位置，不需要移动
      if (movingIndex === targetIndex || movingIndex === targetIndex - 1) {
        this.cancelMove();
        return;
      }
      
      // 执行移动：先删除原位置的项目
      categoryAudios.splice(movingIndex, 1);
      
      // 调整目标位置（如果原位置在目标位置之前，目标位置需要减1）
      let finalTargetIndex = targetIndex;
      if (movingIndex < targetIndex) {
        finalTargetIndex = targetIndex - 1;
      }
      
      // 插入到新位置
      categoryAudios.splice(finalTargetIndex, 0, movingItem);
      
      // 更新分类音频列表
      this.categorizedAudioList[categoryKey] = categoryAudios;
      
      // 同步更新总列表
      this.syncAudioListFromCategories();
      
      const categoryName = this.secondaryCategories[categoryKey].name;
      console.log(
        `${categoryName}内移动完成：${movingItem.name} 从第${movingIndex + 1}位移至第${
          finalTargetIndex + 1
        }位`
      );
      
      // 显示反馈
      const newPosition = finalTargetIndex + 1;
      this.$message.success(`"${movingItem.name}" 已移至第${newPosition}位`);
      
      // 退出移动模式
      this.moveMode = false;
      this.movingAudioIndex = -1;
      this.movingCategoryKey = null;
    },



    // 取消移动模式
    cancelMove() {
      this.moveMode = false;
      this.movingAudioIndex = -1;
      this.movingCategoryKey = null;

      this.$message.info("已取消移动");
    },


    // 格式化时长
    formatDuration(seconds) {
      const min = Math.floor(seconds / 60);
      const sec = seconds % 60;
      return `${min}:${sec.toString().padStart(2, "0")}`;
    },

    // 搜索变化处理
    onSearchChange(e) {
      this.searchText = e.target ? e.target.value : e.detail.value;
      // 防抖处理，500ms后执行搜索
      if (this.searchTimeout) {
        clearTimeout(this.searchTimeout);
      }
      this.searchTimeout = setTimeout(() => {
        this.loadAvailableAudios();
      }, 500);
    },

    // 分类选择变化处理
    onCategoryChange(value) {
      console.log('分类选择变化:', value);
      this.selectedCategory = value;
      
      // 立即重新加载音频列表
      this.loadAvailableAudios();
    },

    // 切换预览音频播放状态
    togglePreviewAudio(audio) {
      console.log('点击音频按钮:', audio.name, '当前状态:', audio.isPlaying);
      
      if (audio.isPlaying) {
        // 当前正在播放，点击后停止播放
        console.log('停止播放:', audio.name);
        audio.isPlaying = false;
        this.isAudioLoading = false;
        // 重置播放进度
        this.currentTime = 0;
        this.playProgress = 0;
        if (this.audioPlayer) {
          this.audioPlayer.stop();
        }
      } else {
        // 当前未播放，点击后开始播放
        console.log('开始播放:', audio.name);
        
        // 先停止所有其他音频
        this.availableAudios.forEach(item => {
          item.isPlaying = false;
        });
        
        // 设置加载状态
        this.isAudioLoading = true;
        this.previewingAudioId = audio.id;
        
        // 开始播放音频
        if (this.audioPlayer) {
          this.audioPlayer.stop();
          this.audioPlayer.loadAudio(audio).then(() => {
            this.isAudioLoading = false;
            audio.isPlaying = true;
            this.audioPlayer.play();
            console.log('音频加载完成，开始播放:', audio.name);
          }).catch(error => {
            console.error('播放失败:', error);
            this.isAudioLoading = false;
            audio.isPlaying = false;
            this.previewingAudioId = null;
          });
        }
      }
      
      console.log('点击后状态:', audio.name, '播放状态:', audio.isPlaying);
    },

    // 开始预览音频
    async startPreviewAudio(audio) {
      console.log("开始预览音频:", audio);

      if (!this.audioPlayer) {
        this.$message.error('音频播放器未初始化');
        return;
      }

      try {
        // 先完全重置所有状态
        const oldPreviewingId = this.previewingAudioId;
        
        // 如果有其他音频正在预览，先停止播放器但不重置previewingAudioId
        if (this.previewingAudioId && this.previewingAudioId !== audio.id) {
          console.log('停止当前播放的音频:', this.previewingAudioId);
          // 只停止播放器，不调用stopPreviewAudio()避免重置状态
          if (this.audioPlayer) {
            this.audioPlayer.stop();
          }
        }

        // 立即设置新状态并更新UI
        this.previewingAudioId = audio.id;
        this.isAudioPlaying = false;
        this.isAudioLoading = true;
        
        console.log('设置新音频状态:', {
          oldPreviewingId,
          newPreviewingId: this.previewingAudioId,
          isAudioPlaying: this.isAudioPlaying,
          isAudioLoading: this.isAudioLoading
        });
        
        // 强制更新UI显示新状态
        this.$forceUpdate();
        
        // 等待一帧确保UI更新
        await this.$nextTick();

        // 加载音频
        const loadSuccess = await this.audioPlayer.loadAudio(audio);
        this.isAudioLoading = false; // 加载完成
        
        if (!loadSuccess) {
          this.previewingAudioId = null;
          this.isAudioPlaying = false;
          this.$forceUpdate();
          return;
        }

        // 播放音频 - 状态更新由事件监听器处理
        const playSuccess = await this.audioPlayer.play();
        if (!playSuccess) {
          this.previewingAudioId = null;
          this.isAudioPlaying = false;
          this.isAudioLoading = false;
          console.log('音频播放失败，重置状态');
        }
        // 播放成功的状态更新由 onPlay 事件监听器处理
        
        // 确保UI状态正确更新
        this.$forceUpdate();
      } catch (error) {
        console.error('预览音频失败:', error);
        this.previewingAudioId = null;
        this.isAudioPlaying = false;
        this.isAudioLoading = false;
        this.$forceUpdate();
        this.$message.error('预览失败: ' + error.message);
      }
    },

    // 暂停/恢复预览音频
    pauseResumePreviewAudio() {
      if (!this.audioPlayer || !this.previewingAudioId) {
        return;
      }

      try {
        if (this.isAudioPlaying) {
          // 当前正在播放，执行暂停 - 状态更新由 onPause 事件监听器处理
          this.audioPlayer.pause();
          console.log('执行暂停音频播放');
        } else {
          // 当前已暂停，执行恢复播放 - 状态更新由 onPlay 事件监听器处理
          this.audioPlayer.play();
          console.log('执行恢复音频播放');
        }
      } catch (error) {
        console.error('暂停/恢复音频失败:', error);
        this.$message.error('操作失败: ' + error.message);
      }
    },

    // 停止预览音频
    stopPreviewAudio() {
      if (this.previewingAudioId) {
        const stoppingAudioId = this.previewingAudioId;
        console.log("停止预览音频:", stoppingAudioId);
        
        // 停止音频播放
        if (this.audioPlayer) {
          this.audioPlayer.stop();
        }

        // 立即重置状态
        this.previewingAudioId = null;
        this.isAudioPlaying = false;
        this.isAudioLoading = false;
        
        console.log('停止音频后状态重置:', {
          stoppedAudioId: stoppingAudioId,
          previewingAudioId: this.previewingAudioId,
          isAudioPlaying: this.isAudioPlaying,
          isAudioLoading: this.isAudioLoading
        });
        
        // 强制更新UI
        this.$forceUpdate();
      }
    },

    // 播放/停止音频（分类播放控制）
    toggleAudioPlay(audioId, categoryKey) {
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      const audio = categoryAudios.find((item) => item.id === audioId);

      if (!audio) return;

      if (audio.isPlaying) {
        // 停止当前音频
        this.stopAudio(audioId, categoryKey);
      } else {
        // 播放音频前，先停止同分类的其他音频
        this.stopCategoryAudios(categoryKey);
        // 开始播放
        this.playAudio(audioId, categoryKey);
      }
    },

    // 播放音频
    playAudio(audioId, categoryKey) {
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      const audio = categoryAudios.find((item) => item.id === audioId);

      if (!audio) return;

      // 检查分类的并发播放限制
      const categoryConfig = this.secondaryCategories[categoryKey].config;
      const playingCount = categoryAudios.filter(
        (item) => item.isPlaying
      ).length;

      if (playingCount >= categoryConfig.maxConcurrent) {
        this.$message({
          message: `${this.secondaryCategories[categoryKey].name}最多同时播放${categoryConfig.maxConcurrent}个音频`,
          type: 'warning'
        });
        return;
      }

      // 设置播放状态
      audio.isPlaying = true;

      // 强制更新视图
      this.$forceUpdate();

      // uni.showToast({
      //   title: `开始播放: ${audio.name}`,
      //   icon: "success",
      // });

      console.log(
        `开始播放：${audio.name} [${this.secondaryCategories[categoryKey].name}]`
      );

      // TODO: 实际的音频播放逻辑
      // 模拟播放结束后自动停止
      const playTimer = setTimeout(() => {
        if (audio.isPlaying) {
          this.stopAudio(audioId, categoryKey);
          // 根据分类配置决定是否自动播放下一个
          if (
            categoryConfig.autoPlay &&
            (categoryConfig.playMode === "sequential" || categoryConfig.playMode === "random")
          ) {
            this.playNextAudio(categoryKey);
          }
        }
      }, audio.duration * 1000);
      
      // 存储定时器引用以便后续清理
      const timerKey = `${categoryKey}_${audioId}`;
      this.audioTimers[timerKey] = playTimer;
      this.globalAudioTimers.push(playTimer);
    },

    // 停止音频
    stopAudio(audioId, categoryKey) {
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      const audio = categoryAudios.find((item) => item.id === audioId);

      if (audio) {
        audio.isPlaying = false;
        
        // 清理该音频的定时器
        const timerKey = `${categoryKey}_${audioId}`;
        if (this.audioTimers[timerKey]) {
          clearTimeout(this.audioTimers[timerKey]);
          delete this.audioTimers[timerKey];
        }
        
        this.$forceUpdate();

        console.log(
          `停止播放：${audio.name} [${this.secondaryCategories[categoryKey].name}]`
        );
      }
    },

    // 停止分类下的所有音频
    stopCategoryAudios(categoryKey) {
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      categoryAudios.forEach((audio) => {
        if (audio.isPlaying) {
          // 使用stopAudio方法来确保定时器也被清理
          this.stopAudio(audio.id, categoryKey);
        }
      });
      
      // 清理分类相关的所有定时器（包括next播放定时器）
      Object.keys(this.audioTimers).forEach(timerKey => {
        if (timerKey.startsWith(`${categoryKey}_`)) {
          clearTimeout(this.audioTimers[timerKey]);
          delete this.audioTimers[timerKey];
        }
      });
      
      this.$forceUpdate();
    },

    // 播放分类下的下一个音频
    playNextAudio(categoryKey) {
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      const categoryConfig = this.secondaryCategories[categoryKey]?.config;

      if (!categoryConfig.autoPlay) return;

      // 找到当前播放的音频索引
      const currentIndex = categoryAudios.findIndex((audio) => audio.isPlaying);
      let nextIndex;

      if (categoryConfig.playMode === "sequential") {
        nextIndex = (currentIndex + 1) % categoryAudios.length;
      } else if (categoryConfig.playMode === "random") {
        const availableIndexes = categoryAudios
          .map((_, index) => index)
          .filter((i) => i !== currentIndex);
        nextIndex =
          availableIndexes[Math.floor(Math.random() * availableIndexes.length)];
      } else {
        return; // 手动播放模式不自动播放下一个
      }

      if (nextIndex !== undefined && categoryAudios[nextIndex]) {
        // 计算随机间隔时间
        const minInterval = categoryConfig.intervalMin;
        const maxInterval = categoryConfig.intervalMax;
        const randomInterval = minInterval === maxInterval 
          ? minInterval 
          : Math.floor(Math.random() * (maxInterval - minInterval + 1)) + minInterval;
          
        const nextPlayTimer = setTimeout(() => {
          this.playAudio(categoryAudios[nextIndex].id, categoryKey);
        }, randomInterval * 1000);
        
        // 存储定时器引用以便后续清理
        const nextTimerKey = `${categoryKey}_next_${Date.now()}`;
        this.audioTimers[nextTimerKey] = nextPlayTimer;
        this.globalAudioTimers.push(nextPlayTimer);
      }
    },

    // 停止所有音频播放
    stopAllAudios() {
      try {
        console.log('开始停止所有音频播放...');
        
        // 1. 停止所有分类的真实音频播放器
        Object.keys(this.audioPlayerInstances).forEach((categoryKey) => {
          this.stopSimpleAudio(categoryKey);
        });
        
        // 2. 停止预览音频播放器
        if (this.audioPlayer) {
          this.audioPlayer.stop();
        }
        this.previewingAudioId = null;
        this.isAudioPlaying = false;
        
        // 3. 停止所有分类的音频播放（清理UI状态）
      Object.keys(this.categorizedAudioList).forEach((categoryKey) => {
        this.stopCategoryAudios(categoryKey);
      });

        // 4. 清理所有全局定时器
        this.globalAudioTimers.forEach(timer => {
          clearTimeout(timer);
        });
        this.globalAudioTimers = [];
        
        // 5. 清理所有音频定时器
        Object.keys(this.audioTimers).forEach(timerKey => {
          clearTimeout(this.audioTimers[timerKey]);
        });
        this.audioTimers = {};
        
        // 6. 清理所有倒计时定时器和播放计划
        Object.keys(this.countdownTimers).forEach(categoryKey => {
          clearInterval(this.countdownTimers[categoryKey]);
        });
        this.countdownTimers = {};
        this.nextPlaySchedule = {};
        
        // 7. 重置所有播放状态
        Object.keys(this.categorizedAudioList).forEach(categoryKey => {
          const categoryAudios = this.categorizedAudioList[categoryKey] || [];
          categoryAudios.forEach(audio => {
            audio.isPlaying = false;
          });
        });
        
        // 7. 重置分类播放状态
        Object.keys(this.playingAudiosByCategory).forEach(categoryKey => {
          this.playingAudiosByCategory[categoryKey] = null;
        });
        
        // 8. 清理所有播放进度信息
        this.categoryPlayProgress = {};
        
        // 8. 强制更新UI
        this.$forceUpdate();
        
        // this.$message({
        //   message: "已停止所有音频播放",
        //   type: 'success'
        // });
        
        console.log('停止所有音频播放完成');
      } catch (error) {
        console.error('停止所有音频播放失败:', error);
      this.$message({
          message: '停止播放失败，请重试',
          type: 'error'
        });
      }
    },

    // 切换所有分类展开状态
    toggleAllCategories() {
      const shouldExpand = !this.allCategoriesExpanded;
      
      // 更新所有分类的展开状态
      Object.keys(this.secondaryCategories).forEach((categoryKey) => {
        if (this.secondaryCategories[categoryKey]) {
          this.secondaryCategories[categoryKey].expanded = shouldExpand;
        }
      });
      
      console.log(shouldExpand ? '展开所有分类完成' : '收起所有分类完成');
      // 注意：展开状态的更改只在本地生效，需要在配置弹窗中点击"保存配置"才会同步到服务器
    },

    // 获取分类播放状态
    getCategoryPlayStatus(categoryKey) {
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      
      // 安全检查：如果分类不存在或数据异常，返回默认状态
      if (!categoryAudios || !Array.isArray(categoryAudios)) {
        console.warn(`分类 ${categoryKey} 的音频列表不存在或数据异常`);
        return {
          playing: false,
          count: 0,
          total: 0,
        };
      }
      
      const playingCount = categoryAudios.filter(
        (audio) => audio && audio.isPlaying
      ).length;
      
      return {
        playing: playingCount > 0,
        count: playingCount,
        total: categoryAudios.length,
      };
    },

    // 获取当前播放音频的名称
    getCurrentPlayingAudioName(categoryKey) {
      const currentPlayingId = this.playingAudiosByCategory[categoryKey];
      if (!currentPlayingId) return '';
      
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      const currentAudio = categoryAudios.find(audio => audio.id === currentPlayingId);
      
      return currentAudio ? currentAudio.name : '未知音频';
    },

    // 切换分类播放状态
    async toggleCategoryPlay(categoryKey) {
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      const categoryConfig = this.secondaryCategories[categoryKey]?.config;
      const playStatus = this.getCategoryPlayStatus(categoryKey);

      if (playStatus.playing) {
        // 如果正在播放，则停止分类播放
        await this.stopCategoryPlay(categoryKey);
      } else {
        // 开始分类播放
        await this.startCategoryPlay(categoryKey);
      }
    },

    // 开始分类播放
    async startCategoryPlay(categoryKey) {
      try {
        const categoryAudios = this.categorizedAudioList[categoryKey] || [];
        const categoryConfig = this.secondaryCategories[categoryKey]?.config;
        const categoryName = this.secondaryCategories[categoryKey]?.name;

        if (categoryAudios.length === 0) {
          this.$message.warning(`${categoryName}中暂无音频`);
          return;
        }

        console.log(`开始播放分类 [${categoryName}]，包含 ${categoryAudios.length} 个音频`);
        console.log(`分类配置 [${categoryName}]:`, {
          播放模式: categoryConfig.playMode,
          自动播放: categoryConfig.autoPlay,
          间隔时间: `${categoryConfig.intervalMin}-${categoryConfig.intervalMax}秒`,
          分类内并发: categoryConfig.maxConcurrent,
          音量设置: categoryConfig.volume ? `${(categoryConfig.volume * 100).toFixed(0)}%` : '默认',
          循环播放: categoryConfig.loop !== false
        });

        // maxConcurrent只控制单个分类内的音频并发数量，不限制分类间的并发播放

        // 创建或获取该分类的播放器实例
        if (!this.audioPlayerInstances[categoryKey]) {
          this.audioPlayerInstances[categoryKey] = new AudioPlayer();
          this.setupCategoryPlayerEvents(categoryKey);
          console.log(`创建分类播放器 [${categoryName}] 并设置事件监听`);
        }

        const playerInstance = this.audioPlayerInstances[categoryKey];

        // 选择要播放的音频
        let targetIndex = 0;
          if (categoryConfig.playMode === "random") {
            targetIndex = Math.floor(Math.random() * categoryAudios.length);
          }

        const targetAudio = categoryAudios[targetIndex];
        
        // 确保音频对象有正确的路径
        const audioForPlayer = {
          ...targetAudio,
          file_path: targetAudio.path || targetAudio.file_path
        };

        // 使用统一的播放方法（包含随机片段播放逻辑）
        console.log(`开始播放分类 [${categoryName}] 的第一首音频: ${targetAudio.name}`);
        console.log(`播放配置 [${categoryName}]:`, {
          播放模式: categoryConfig.playMode,
          自动播放: categoryConfig.autoPlay,
          间隔范围: `${categoryConfig.intervalMin}-${categoryConfig.intervalMax}秒`,
          分类内并发: categoryConfig.maxConcurrent,
          音量: categoryConfig.volume ? `${(categoryConfig.volume * 100).toFixed(0)}%` : '默认',
          随机片段播放: categoryConfig.randomFragment ? '启用' : '禁用'
        });
        
        // 调用统一的播放方法，应用所有播放规则
        await this.playCategoryAudio(categoryKey, targetAudio);

      } catch (error) {
        console.error('开始分类播放失败:', error);
        this.$message.error('播放失败: ' + error.message);
      }
    },

    // 停止分类播放
    async stopCategoryPlay(categoryKey) {
      try {
        const categoryName = this.secondaryCategories[categoryKey]?.name;
        console.log(`停止播放分类 [${categoryName}]`);

        // 停止播放器
        await this.stopSimpleAudio(categoryKey);
        
        // 清理该分类的定时器
        Object.keys(this.audioTimers).forEach(timerKey => {
          if (timerKey.startsWith(`${categoryKey}_`)) {
            clearTimeout(this.audioTimers[timerKey]);
            delete this.audioTimers[timerKey];
          }
        });
        
        // 清理下一首播放计划
        this.clearNextPlaySchedule(categoryKey);

        console.log(`已停止播放分类 [${categoryName}]`);
      } catch (error) {
        console.error('停止分类播放失败:', error);
        this.$message.error('停止播放失败: ' + error.message);
      }
    },


    // 安排下一首音频播放
    scheduleNextCategoryAudio(categoryKey, currentAudio) {
      const categoryConfig = this.secondaryCategories[categoryKey]?.config;
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];

      console.log(`⏰ 安排下一首播放 [${categoryKey}]:`, {
        当前音频: currentAudio.name,
        自动播放: categoryConfig?.autoPlay,
        播放模式: categoryConfig?.playMode
      });

      if (!categoryConfig.autoPlay || categoryConfig.playMode === "single") {
        console.log(`❌ 不安排自动播放: 自动播放=${categoryConfig?.autoPlay}, 播放模式=${categoryConfig?.playMode}`);
        return; // 不自动播放下一首
      }

      // 设置播放结束后的处理
      const playerInstance = this.audioPlayerInstances[categoryKey];
      if (playerInstance) {
        console.log(`✅ 设置播放结束监听器 [${categoryKey}]: ${currentAudio.name}`);
        
        // 监听播放结束事件
        playerInstance.onEnded(() => {
          console.log(`🔚 音频播放结束事件触发 [${categoryKey}]: ${currentAudio.name}`);
          
          // 重置当前音频状态
          this.playingAudiosByCategory[categoryKey] = null;
          this.updatePlayingState();
          
          // 计算下一首音频
          console.log(`🎯 开始计算并播放下一首...`);
          this.playNextCategoryAudio(categoryKey, currentAudio);
        });
      } else {
        console.error(`❌ 播放器实例不存在，无法设置监听器 [${categoryKey}]`);
      }
    },

    // 播放分类的下一首音频
    async playNextCategoryAudio(categoryKey, currentAudio = null) {
      try {
        const categoryAudios = this.categorizedAudioList[categoryKey] || [];
        const categoryConfig = this.secondaryCategories[categoryKey]?.config;
        
        console.log(`🎵 播放下一首检查 [${categoryKey}]:`, {
          分类名称: this.secondaryCategories[categoryKey]?.name,
          音频总数: categoryAudios.length,
          自动播放: categoryConfig?.autoPlay,
          播放模式: categoryConfig?.playMode,
          完整配置: categoryConfig
        });

        if (!categoryConfig || !categoryConfig.autoPlay || categoryAudios.length === 0) {
          console.log(`❌ 停止自动播放 [${categoryKey}]: 配置=${!!categoryConfig}, 自动播放=${categoryConfig?.autoPlay}, 音频数=${categoryAudios.length}`);
          return;
        }

        console.log(`开始计算下一首音频 [${categoryKey}], 播放模式: ${categoryConfig.playMode}`);

        // 选择下一首音频（根据播放模式配置）
        let nextIndex = 0;
        
        if (categoryConfig.playMode === "sequential") {
          // 顺序播放模式 - 一直循环播放
          let currentIndex = -1;
          if (currentAudio) {
            // 使用传入的当前音频
            currentIndex = categoryAudios.findIndex(audio => audio.id === currentAudio.id);
          } else {
            // 回退到使用播放状态中的音频ID
            const currentPlayingId = this.playingAudiosByCategory[categoryKey];
            currentIndex = categoryAudios.findIndex(audio => audio.id === currentPlayingId);
          }
          
          nextIndex = (currentIndex + 1) % categoryAudios.length;
          console.log(`顺序播放: 当前索引=${currentIndex}, 下一个索引=${nextIndex} (循环播放)`);
          
          // 顺序播放模式总是循环播放，除非用户手动停止
        } else if (categoryConfig.playMode === "random") {
          // 随机播放模式 - 一直循环播放
          nextIndex = Math.floor(Math.random() * categoryAudios.length);
          console.log(`随机播放: 选择索引=${nextIndex} (循环播放)`);
        } else if (categoryConfig.playMode === "loop") {
          // 单曲循环模式 - 重复播放当前音频
          if (currentAudio) {
            nextIndex = categoryAudios.findIndex(audio => audio.id === currentAudio.id);
          } else {
            const currentPlayingId = this.playingAudiosByCategory[categoryKey];
            nextIndex = categoryAudios.findIndex(audio => audio.id === currentPlayingId);
          }
          nextIndex = nextIndex >= 0 ? nextIndex : 0;
          console.log(`单曲循环播放: 选择索引=${nextIndex}, 音频=${categoryAudios[nextIndex]?.name}`);
        } else if (categoryConfig.playMode === "manual") {
          // 手动播放模式 - 不自动播放下一首
          console.log(`分类 [${categoryKey}] 手动播放模式，不自动播放下一首`);
          return;
        } else {
          // 默认顺序播放
          let currentIndex = -1;
          if (currentAudio) {
            currentIndex = categoryAudios.findIndex(audio => audio.id === currentAudio.id);
          } else {
            const currentPlayingId = this.playingAudiosByCategory[categoryKey];
            currentIndex = categoryAudios.findIndex(audio => audio.id === currentPlayingId);
          }
          nextIndex = (currentIndex + 1) % categoryAudios.length;
          console.log(`默认播放: 当前索引=${currentIndex}, 下一个索引=${nextIndex}`);
        }

        // 计算间隔时间
        const minInterval = categoryConfig.intervalMin || 0;
        const maxInterval = categoryConfig.intervalMax || 0;
        const intervalTime = minInterval === maxInterval 
          ? minInterval 
          : Math.floor(Math.random() * (maxInterval - minInterval + 1)) + minInterval;

        const nextAudio = categoryAudios[nextIndex];
        if (!nextAudio) {
          console.error(`下一首音频不存在，索引=${nextIndex}, 总数=${categoryAudios.length}`);
          return;
        }

        console.log(`将在 ${intervalTime} 秒后播放下一首音频: ${nextAudio.name}`);

        // 设置下一首播放计划显示
        this.setNextPlaySchedule(categoryKey, nextAudio, intervalTime);

        // 设置定时器播放下一首
        const nextTimer = setTimeout(async () => {
          console.log(`定时器触发，开始播放下一首: ${nextAudio.name}`);
          // 清理下一首播放计划显示
          this.clearNextPlaySchedule(categoryKey);
          await this.playCategoryAudio(categoryKey, nextAudio);
        }, intervalTime * 1000);

        // 存储定时器
        const timerKey = `${categoryKey}_next_${Date.now()}`;
        this.audioTimers[timerKey] = nextTimer;
        this.globalAudioTimers.push(nextTimer);

      } catch (error) {
        console.error('播放下一首音频失败:', error);
      }
    },

    // 播放分类中的指定音频
    async playCategoryAudio(categoryKey, audio) {
      try {
        const playerInstance = this.audioPlayerInstances[categoryKey];
        if (!playerInstance) {
          console.error('播放器实例不存在:', categoryKey);
          return;
        }

        const audioForPlayer = {
          ...audio,
          file_path: audio.path || audio.file_path
        };

        console.log(`播放分类音频 [${categoryKey}]:`, audioForPlayer.name);

        const loadSuccess = await playerInstance.loadAudio(audioForPlayer);
        if (!loadSuccess) {
          console.error('音频加载失败:', audioForPlayer);
          return;
        }

        // 应用音量配置（直接使用音频音量）
        const audioVolume = this.getAudioVolume(audio.id) / 100;
        
        // 使用AudioPlayer的setVolume方法
        playerInstance.setVolume(audioVolume);
        console.log(`设置音量 [${categoryKey}]: 音频音量${Math.round(audioVolume * 100)}%`);

        // 检查是否使用随机片段播放
        const fragmentConfig = this.calculateFragmentPlayback(categoryKey, audio, playerInstance.duration);
        
        if (fragmentConfig.useFragment) {
          // 使用随机片段播放
          console.log(`使用随机片段播放 [${categoryKey}]: ${audio.name}`, {
            startTime: fragmentConfig.startTime,
            duration: fragmentConfig.duration,
            strategy: fragmentConfig.strategy
          });
          
          // 设置播放起始时间
          playerInstance.setCurrentTime(fragmentConfig.startTime);
          
          // 开始播放
          const playSuccess = await playerInstance.play();
          if (playSuccess) {
            this.playingAudiosByCategory[categoryKey] = audio.id;
            
            // 应用音量设置
            this.applyCategoryVolume(categoryKey);
            
            this.updatePlayingState();
            
            console.log(`片段播放开始 [${categoryKey}]: ${audio.name} (${fragmentConfig.startTime.toFixed(1)}s - ${(fragmentConfig.startTime + fragmentConfig.duration).toFixed(1)}s)`);
            
            // 设置片段播放定时器 - 在指定时长后停止
            const fragmentTimer = setTimeout(() => {
              if (this.playingAudiosByCategory[categoryKey] === audio.id) {
                console.log(`⏰ 片段播放时间到，停止播放 [${categoryKey}]: ${audio.name}`);
                console.log(`📊 当前配置检查:`, {
                  自动播放: categoryConfig.autoPlay,
                  播放模式: categoryConfig.playMode,
                  间隔设置: `${categoryConfig.intervalMin}-${categoryConfig.intervalMax}秒`
                });
                
                playerInstance.stop();
                
                // 先触发播放下一首（此时还能获取到当前音频ID）
                console.log(`🔄 准备触发自动播放下一首...`);
                this.playNextCategoryAudio(categoryKey, audio);
                
                // 然后清理当前播放状态
                this.playingAudiosByCategory[categoryKey] = null;
                this.updatePlayingState();
              } else {
                console.log(`⚠️ 片段播放定时器触发但音频已切换: 期望=${audio.id}, 当前=${this.playingAudiosByCategory[categoryKey]}`);
              }
            }, fragmentConfig.duration * 1000);
            
            // 存储片段定时器
            const timerKey = `${categoryKey}_fragment_${audio.id}`;
            this.audioTimers[timerKey] = fragmentTimer;
            this.globalAudioTimers.push(fragmentTimer);
          }
        } else {
          // 正常完整播放
          const playSuccess = await playerInstance.play();
          if (playSuccess) {
            this.playingAudiosByCategory[categoryKey] = audio.id;
            
            // 应用音量设置
            this.applyCategoryVolume(categoryKey);
            
            this.updatePlayingState();
            
            console.log(`🎵 完整播放开始 [${categoryKey}]: ${audio.name}`);
            console.log(`📊 完整播放配置检查:`, {
              自动播放: categoryConfig.autoPlay,
              播放模式: categoryConfig.playMode,
              间隔设置: `${categoryConfig.intervalMin}-${categoryConfig.intervalMax}秒`
            });
            
            // 设置自动播放下一首
            console.log(`⚙️ 设置播放结束监听器...`);
            this.scheduleNextCategoryAudio(categoryKey, audio);
          }
        }

      } catch (error) {
        console.error('播放分类音频失败:', error);
      }
    },

    // 设置下一首播放计划
    setNextPlaySchedule(categoryKey, nextAudio, intervalTime) {
      // 清理之前的倒计时定时器
      this.clearCountdownTimer(categoryKey);
      
      // 设置下一首播放计划
      this.$set(this.nextPlaySchedule, categoryKey, {
        nextAudio: nextAudio,
        countdown: intervalTime,
        totalInterval: intervalTime
      });
      
      // 开始倒计时
      this.startCountdownTimer(categoryKey);
      
      console.log(`📅 设置下一首播放计划 [${categoryKey}]: ${nextAudio.name}, ${intervalTime}秒后播放`);
    },
    
    // 清理下一首播放计划
    clearNextPlaySchedule(categoryKey) {
      this.clearCountdownTimer(categoryKey);
      this.$delete(this.nextPlaySchedule, categoryKey);
      console.log(`🧹 清理下一首播放计划 [${categoryKey}]`);
    },
    
    // 开始倒计时定时器
    startCountdownTimer(categoryKey) {
      const updateCountdown = () => {
        if (this.nextPlaySchedule[categoryKey]) {
          if (this.nextPlaySchedule[categoryKey].countdown > 0) {
            this.nextPlaySchedule[categoryKey].countdown--;
            this.$forceUpdate();
          } else {
            this.clearCountdownTimer(categoryKey);
          }
        }
      };
      
      // 每秒更新一次倒计时
      const timer = setInterval(updateCountdown, 1000);
      this.$set(this.countdownTimers, categoryKey, timer);
      
      console.log(`⏰ 开始倒计时定时器 [${categoryKey}]`);
    },
    
    // 清理倒计时定时器
    clearCountdownTimer(categoryKey) {
      if (this.countdownTimers[categoryKey]) {
        clearInterval(this.countdownTimers[categoryKey]);
        this.$delete(this.countdownTimers, categoryKey);
        console.log(`🛑 清理倒计时定时器 [${categoryKey}]`);
      }
    },
    
    // 格式化倒计时显示
    formatCountdown(seconds) {
      if (seconds <= 0) return '即将播放';
      
      const mins = Math.floor(seconds / 60);
      const secs = seconds % 60;
      
      if (mins > 0) {
        return `${mins}:${secs.toString().padStart(2, '0')}`;
      } else {
        return `${secs}s`;
      }
    },
    
    // 获取播放模式文本
    getPlayModeText(categoryKey) {
      const config = this.secondaryCategories[categoryKey]?.config;
      if (!config) return '';
      
      const modeTexts = {
        'sequential': '顺序播放',
        'random': '随机播放', 
        'loop': '单曲循环',
        'manual': '手动播放'
      };
      
      const modeText = modeTexts[config.playMode] || '顺序播放';
      const intervalText = config.intervalMin === config.intervalMax 
        ? `${config.intervalMin}s间隔` 
        : `${config.intervalMin}-${config.intervalMax}s间隔`;
        
      return `${modeText} · ${intervalText}`;
    },

    // 计算随机片段播放参数
    calculateFragmentPlayback(categoryKey, audio, audioDuration) {
      const categoryConfig = this.secondaryCategories[categoryKey]?.config;
      
      // 默认返回不使用片段播放
      const defaultResult = {
        useFragment: false,
        startTime: 0,
        duration: audioDuration || 0,
        strategy: 'complete'
      };
      
      // 检查是否启用了随机片段播放
      if (!categoryConfig || !categoryConfig.randomFragment) {
        return defaultResult;
      }
      
      // 检查音频时长是否足够（需要音频元数据）
      const actualDuration = audioDuration || audio.duration || 0;
      const minAudioLength = categoryConfig.fragmentMinAudioLength || 15;
      
      if (actualDuration < minAudioLength) {
        console.log(`音频时长 ${actualDuration.toFixed(1)}s < 最小长度 ${minAudioLength}s，使用完整播放`);
        return defaultResult;
      }
      
      // 根据概率决定是否使用片段播放
      const probability = categoryConfig.fragmentProbability || 35;
      const shouldUseFragment = Math.random() * 100 < probability;
      
      if (!shouldUseFragment) {
        console.log(`根据概率 ${probability}% 决定使用完整播放`);
        return defaultResult;
      }
      
      // 计算片段时长
      const minDuration = categoryConfig.fragmentMinDuration || 3;
      const maxDuration = categoryConfig.fragmentMaxDuration || 8;
      const fragmentDuration = minDuration === maxDuration 
        ? minDuration 
        : Math.random() * (maxDuration - minDuration) + minDuration;
      
      // 确保片段时长不超过音频总时长
      const actualFragmentDuration = Math.min(fragmentDuration, actualDuration);
      
      // 计算起始时间（根据策略）
      let startTime = 0;
      const strategy = categoryConfig.fragmentStartStrategy || 'avoid_start';
      const maxStartTime = actualDuration - actualFragmentDuration;
      
      switch (strategy) {
        case 'random':
          // 完全随机选择起始时间
          startTime = Math.random() * maxStartTime;
          break;
          
        case 'avoid_start':
          // 避开开头（跳过前面20%的部分）
          const avoidStartTime = actualDuration * 0.2;
          startTime = avoidStartTime + Math.random() * (maxStartTime - avoidStartTime);
          break;
          
        case 'middle_focus':
          // 中段优先（优先选择中间40%-80%的部分）
          const middleStart = actualDuration * 0.4;
          const middleEnd = actualDuration * 0.8;
          const availableMiddleTime = Math.min(middleEnd, maxStartTime) - middleStart;
          
          if (availableMiddleTime > 0) {
            startTime = middleStart + Math.random() * availableMiddleTime;
          } else {
            // 如果中段不够，回退到避开开头策略
            const avoidStartTime = actualDuration * 0.2;
            startTime = avoidStartTime + Math.random() * (maxStartTime - avoidStartTime);
          }
          break;
          
        default:
          startTime = Math.random() * maxStartTime;
      }
      
      // 确保起始时间不为负数且在有效范围内
      startTime = Math.max(0, Math.min(startTime, maxStartTime));
      
      return {
        useFragment: true,
        startTime: startTime,
        duration: actualFragmentDuration,
        strategy: strategy,
        originalDuration: actualDuration,
        probability: probability
      };
    },

    // 显示分类配置
    showCategoryConfig(categoryKey) {
      this.currentConfigCategory = categoryKey;
      this.categoryConfigVisible = true;
    },

    // 关闭分类配置
    closeCategoryConfig() {
      this.categoryConfigVisible = false;
      this.currentConfigCategory = null;
    },

    // 分类配置弹窗完全关闭后的回调
    onCategoryConfigClosed() {
      // 弹窗完全关闭后清理状态
      this.currentConfigCategory = null;
    },

    // 更新本地分类配置
    updateLocalConfig(configKey, value) {
      if (this.currentConfigCategory) {
        this.secondaryCategories[this.currentConfigCategory].config[configKey] =
          value;

        // 强制更新视图
        this.$forceUpdate();

        console.log(
          `${
            this.secondaryCategories[this.currentConfigCategory].name
          } 配置更新: ${configKey} = ${value}`
        );
      }
    },

    // 播放间隔变化处理（滑块）
    onIntervalChange(e) {
      const value = e.detail ? e.detail.value : e.target.value;
      this.updateLocalConfig("interval", parseInt(value));
    },

    // 已移除 onIntervalMinChange 和 onIntervalMaxChange 方法，现在使用 v-model 双向绑定

    // 随机片段播放开关变化处理
    onRandomFragmentChange(e) {
      const checked = e.detail ? e.detail.value : e.target.checked;
      this.updateLocalConfig("randomFragment", checked);
      
      // 如果启用随机片段播放，设置推荐的默认值
      if (checked && this.currentConfigCategory) {
        const config = this.secondaryCategories[this.currentConfigCategory].config;
        if (!config.fragmentMinDuration) {
          this.updateLocalConfig("fragmentMinDuration", 3);
        }
        if (!config.fragmentMaxDuration) {
          this.updateLocalConfig("fragmentMaxDuration", 8);
        }
        if (!config.fragmentProbability) {
          this.updateLocalConfig("fragmentProbability", 35); // 推荐35%概率，既能降重复又不会太乱
        }
        if (!config.fragmentMinAudioLength) {
          this.updateLocalConfig("fragmentMinAudioLength", 15); // 推荐15秒以上才使用片段播放
        }
        if (!config.fragmentStartStrategy) {
          this.updateLocalConfig("fragmentStartStrategy", "avoid_start"); // 推荐避开开头策略
        }
      }
    },

    // 最短播放时间变化处理
    onFragmentMinDurationChange(value) {
      if (this.currentConfigCategory && value !== undefined) {
        this.updateLocalConfig("fragmentMinDuration", parseInt(value));
        console.log(`最短播放时间更新为: ${value}秒`);
      }
    },

    // 最长播放时间变化处理
    onFragmentMaxDurationChange(value) {
      if (this.currentConfigCategory && value !== undefined) {
        this.updateLocalConfig("fragmentMaxDuration", parseInt(value));
        console.log(`最长播放时间更新为: ${value}秒`);
      }
    },

    // 获取片段播放预览文本
    getFragmentPreviewText(categoryKey) {
      if (!categoryKey || !this.categorizedAudioList[categoryKey]) {
        return "暂无音频";
      }
      
      const config = this.secondaryCategories[categoryKey].config;
      const audios = this.categorizedAudioList[categoryKey];
      const totalCount = audios.length;
      
      if (totalCount === 0) {
        return "暂无音频";
      }
      
      const probability = config.fragmentProbability || 35;
      const minLength = config.fragmentMinAudioLength || 15;
      
      // 估算有多少音频适合片段播放（这里简化处理，假设70%的音频长度≥15秒）
      const longAudioEstimate = Math.ceil(totalCount * 0.7);
      const fragmentPlayEstimate = Math.ceil(longAudioEstimate * probability / 100);
      
      return `共${totalCount}首音频，约${fragmentPlayEstimate}首会播放片段，${totalCount - fragmentPlayEstimate}首完整播放`;
    },

    // 应用片段播放预设配置
    applyFragmentPreset(presetType) {
      if (!this.currentConfigCategory) return;
      
      const presets = {
        conservative: {
          // 🛡️ 保守模式 - 适合初次使用，温和降重
          fragmentProbability: 20,
          fragmentMinDuration: 4,
          fragmentMaxDuration: 8,
          fragmentMinAudioLength: 20,
          fragmentStartStrategy: "avoid_start"
        },
        balanced: {
          // ⚖️ 平衡模式 - 日常推荐，平衡效果与体验
          fragmentProbability: 35,
          fragmentMinDuration: 3,
          fragmentMaxDuration: 8,
          fragmentMinAudioLength: 15,
          fragmentStartStrategy: "avoid_start"
        },
        aggressive: {
          // 🚀 激进模式 - 最大化降重复率
          fragmentProbability: 60,
          fragmentMinDuration: 2,
          fragmentMaxDuration: 6,
          fragmentMinAudioLength: 12,
          fragmentStartStrategy: "random"
        },
        stealth: {
          // 🥷 隐蔽模式 - 专门针对检测算法优化
          fragmentProbability: 45,
          fragmentMinDuration: 3,
          fragmentMaxDuration: 7,
          fragmentMinAudioLength: 18,
          fragmentStartStrategy: "middle_focus"
        }
      };
      
      const preset = presets[presetType];
      if (!preset) return;
      
      // 批量更新配置
      Object.keys(preset).forEach(key => {
        this.updateLocalConfig(key, preset[key]);
      });
      
      // 显示应用成功的消息
      const modeNames = {
        conservative: "保守模式",
        balanced: "平衡模式", 
        aggressive: "激进模式",
        stealth: "隐蔽模式"
      };
      
      this.$message({
        message: `已应用${modeNames[presetType]}设置`,
        type: 'success',
        duration: 2000
      });
    },

    // 自动播放开关变化处理
    onAutoPlayChange(e) {
      const checked = e.detail ? e.detail.value : e.target.checked;
      this.updateLocalConfig("autoPlay", checked);
    },


    // 保存分类配置
    async saveCategoryConfig() {
      if (!this.currentConfigCategory) return;

      const categoryName =
        this.secondaryCategories[this.currentConfigCategory].name;

      try {
        // 调用后端API保存配置
        await this.updateCategoryConfig(
          this.currentConfigCategory,
          this.secondaryCategories[this.currentConfigCategory].config
        );

        this.$message.success(`${categoryName} 配置已保存`);

        console.log(
          `${categoryName} 配置已保存:`,
          this.secondaryCategories[this.currentConfigCategory].config
        );

        this.closeCategoryConfig();
      } catch (error) {
        console.error('保存分类配置失败:', error);
        this.$message.error(`保存${categoryName}配置失败: ${error}`);
      }
    },

    // 重置分类配置
    resetCategoryConfig() {
      if (!this.currentConfigCategory) return;

      const categoryKey = this.currentConfigCategory;
      const categoryName = this.secondaryCategories[categoryKey].name;

      // 临时隐藏配置弹窗以避免层级问题
      const originalVisible = this.categoryConfigVisible;
      this.categoryConfigVisible = false;

      uni.showModal({
        title: "重置配置",
        content: `确定要重置"${categoryName}"的配置到默认设置吗？`,
        success: (res) => {
          // 恢复配置弹窗显示
          this.categoryConfigVisible = originalVisible;
          
          if (res.confirm) {
            // 重置到默认配置
            const defaultConfigs = {
              scene: {
                playMode: "sequential",
                intervalMin: 20,
                intervalMax: 40,
                autoPlay: true,
                maxConcurrent: 1,
                randomFragment: false,
                fragmentMinDuration: 3,
                fragmentMaxDuration: 8,
                fragmentProbability: 35,
                fragmentMinAudioLength: 15,
                fragmentStartStrategy: "avoid_start",
              },
              background: {
                playMode: "loop",
                intervalMin: 0,
                intervalMax: 0,
                autoPlay: false,
                maxConcurrent: 1,
                volume: 0.3,
                randomFragment: false,
                fragmentMinDuration: 3,
                fragmentMaxDuration: 8,
                fragmentProbability: 35,
                fragmentMinAudioLength: 15,
                fragmentStartStrategy: "avoid_start",
              },
              other: {
                playMode: "manual",
                intervalMin: 5,
                intervalMax: 15,
                autoPlay: false,
                maxConcurrent: 1,
                randomFragment: false,
                fragmentMinDuration: 3,
                fragmentMaxDuration: 8,
                fragmentProbability: 35,
                fragmentMinAudioLength: 15,
                fragmentStartStrategy: "avoid_start",
              },
            };

            // 如果是自定义分类，使用通用默认配置
            let resetConfig = defaultConfigs[categoryKey];
            if (!resetConfig) {
              resetConfig = {
                playMode: "sequential",
                intervalMin: 10,
                intervalMax: 30,
                autoPlay: false,
                maxConcurrent: 1,
                randomFragment: false,
                fragmentMinDuration: 3,
                fragmentMaxDuration: 8,
                fragmentProbability: 35,
                fragmentMinAudioLength: 15,
                fragmentStartStrategy: "avoid_start",
              };
            }

            this.secondaryCategories[categoryKey].config = {
              ...resetConfig,
            };
            this.$forceUpdate();

            this.$message({
              message: `${categoryName} 配置已重置`,
              type: 'success'
            });

            console.log(`${categoryName} 配置已重置为默认设置`);
          }
        },
        fail: () => {
          // 如果弹窗失败，也要恢复配置弹窗显示
          this.categoryConfigVisible = originalVisible;
        }
      });
    },

    // 处理添加分类按钮点击
    handleAddCategoryClick() {
      this.showAddCategory();
    },

    // 显示添加分类弹窗
    showAddCategory() {
      this.resetNewCategory();
      this.addCategoryVisible = true;
    },

    // 关闭添加分类弹窗
    closeAddCategory() {
      this.addCategoryVisible = false;
      this.resetNewCategory();
    },

    // 添加分类弹窗完全关闭后的回调
    onAddCategoryClosed() {
      // 弹窗完全关闭后清理状态
      this.resetNewCategory();
    },

    // 重置新分类数据
    resetNewCategory() {
      this.newCategory = {
        key: '',
        name: '',
        description: '',
        icon: '🎵',
        subCategories: []
      };
    },

    // 选择图标
    selectIcon(icon) {
      this.newCategory.icon = icon;
    },


    // 输入框获得焦点
    onInputFocus(e) {
      console.log('输入框获得焦点');
    },

    // 输入框失去焦点  
    onInputBlur(e) {
      console.log('输入框失去焦点');
    },

    // 确认添加分类
    async confirmAddCategory() {
      const categoryName = this.newCategory.name.trim();
      if (!categoryName) {
        this.$message.warning("请输入分类名称");
        return;
      }

      // 防止重复提交
      if (this.addCategoryLoading) {
        return;
      }
      
      this.addCategoryLoading = true;

      // 生成唯一的key
      const categoryKey = 'custom_' + Date.now();
      
      // 检查是否重名
      const existingNames = Object.values(this.secondaryCategories).map(cat => cat.name);
      if (existingNames.includes(categoryName)) {
        this.$message.warning("分类名称已存在");
        this.addCategoryLoading = false;
        return;
      }

      // 创建新分类
      const newCategoryData = {
        name: categoryName,
        description: this.newCategory.description.trim() || `${categoryName}相关音频`,
        icon: this.newCategory.icon,
        subCategories: [categoryName], // 将分类名称加入子分类
        config: {
          playMode: "sequential",
          intervalMin: 10,
          intervalMax: 30,
          autoPlay: false,
          maxConcurrent: 1,
          randomFragment: false,
          fragmentMinDuration: 3,
          fragmentMaxDuration: 8,
          fragmentProbability: 35,
          fragmentMinAudioLength: 15,
          fragmentStartStrategy: "avoid_start",
        },
        expanded: true,
      };

      try {
        // 调用后端API创建分类
        const categoryData = {
          room_id: this.currentRoom.id,
          category_type: categoryKey,
          category_name: categoryName,
          description: this.newCategory.description.trim() || `${categoryName}相关音频`,
          icon: this.newCategory.icon,
          config: {
            playMode: "sequential",
            intervalMin: 10,
            intervalMax: 30,
            autoPlay: false,
            volume: 1.00,
            randomFragment: false,
            fragmentMinDuration: 3,
            fragmentMaxDuration: 8,
            fragmentProbability: 35,
            fragmentMinAudioLength: 15,
            fragmentStartStrategy: "avoid_start",
          }
        };

        const result = await createRoomCategory(categoryData);
        console.log('后端创建分类成功:', result);

        // 添加到分类列表
        this.$set(this.secondaryCategories, categoryKey, newCategoryData);
        
        // 初始化分类音频列表
        this.$set(this.categorizedAudioList, categoryKey, []);

        // 添加到分类选择器选项
        this.categoryOptions.push({
          label: categoryName,
          value: categoryName
        });

        console.log(`新增分类：${categoryName}`);

        this.$message({
          message: `分类"${categoryName}"创建成功并已保存`,
          type: 'success'
        });

        this.closeAddCategory();
        
      } catch (error) {
        console.error('创建分类失败:', error);
        this.$message({
          message: `创建分类失败: ${error}`,
          type: 'error',
          duration: 3000
        });
      } finally {
        // 重置loading状态
        this.addCategoryLoading = false;
      }
    },

    // 定位播放音频在列表中的位置
    locateAudioInList(playingInfo) {
      const categoryKey = playingInfo.categoryKey;
      const audioId = playingInfo.audio.id;

      try {
        // 1. 展开对应的分类
        if (!this.secondaryCategories[categoryKey].expanded) {
          this.secondaryCategories[categoryKey].expanded = true;
          this.$forceUpdate();
        }

        // 2. 高亮显示该音频
        this.highlightedAudioId = audioId;

        // 3. 使用nextTick确保DOM更新后再滚动
        this.$nextTick(() => {
          const targetElement = uni.createSelectorQuery().select(`#audio-item-${audioId}`);
          if (targetElement) {
            // 滚动到目标位置
            uni.pageScrollTo({
              selector: `#audio-item-${audioId}`,
              duration: 300,
              success: () => {
                console.log('成功定位到音频：', playingInfo.audio.name);
              },
              fail: (err) => {
                console.log('定位失败：', err);
                // 尝试另一种方式 - 通过分类滚动
                this.scrollToCategoryAudio(categoryKey, audioId);
              }
            });
          } else {
            // 如果直接定位失败，尝试滚动到分类区域
            this.scrollToCategoryAudio(categoryKey, audioId);
          }

          // 4. 3秒后取消高亮
          setTimeout(() => {
            this.highlightedAudioId = null;
          }, 3000);
        });

        // 显示提示信息
        // uni.showToast({
        //   title: `定位到：${playingInfo.audio.name}`,
        //   icon: "none",
        //   duration: 1500
        // });

      } catch (error) {
        console.error('定位音频时出错:', error);
        this.$message.error("定位失败，请手动查找");
      }
    },

    // 滚动到分类中的特定音频
    scrollToCategoryAudio(categoryKey, audioId) {
      // 先滚动到分类标题
      const categorySelector = `.category-section:nth-child(${Object.keys(this.secondaryCategories).indexOf(categoryKey) + 1})`;
      
      uni.pageScrollTo({
        selector: categorySelector,
        duration: 300,
        success: () => {
          console.log('已定位到分类区域');
          // 再次尝试滚动到具体音频
          setTimeout(() => {
            uni.pageScrollTo({
              selector: `#audio-item-${audioId}`,
              duration: 200,
              fail: () => {
                console.log('无法精确定位到音频项');
              }
            });
          }, 400);
        },
        fail: () => {
          console.log('无法定位到分类区域');
        }
      });
    },

    // 处理删除分类按钮点击
    handleDeleteCategoryClick(categoryKey) {
      console.log('删除分类按钮被点击，分类Key:', categoryKey);
      console.log('当前所有分类:', Object.keys(this.secondaryCategories));
      console.log('当前分类播放状态:', this.getCategoryPlayStatus(categoryKey));
      this.deleteCategory(categoryKey);
    },

    // 删除分类
    deleteCategory(categoryKey) {
      console.log(`尝试删除分类：${categoryKey}`);
      
      const categoryInfo = this.secondaryCategories[categoryKey];
      if (!categoryInfo) {
        console.error(`分类不存在：${categoryKey}`);
        console.error('当前可用分类：', Object.keys(this.secondaryCategories));
        this.$message({
          message: "分类不存在",
          type: 'error'
        });
        return;
      }

      // 检查是否有音频正在播放
      const playStatus = this.getCategoryPlayStatus(categoryKey);
      if (playStatus.playing) {
        console.log(`分类 ${categoryKey} 有音频正在播放，无法删除`);
        this.$message({
          message: "请先停止该分类的音频播放",
          type: 'warning',
          duration: 2000
        });
        return;
      }

      // 额外的数据完整性检查
      if (!this.secondaryCategories.hasOwnProperty(categoryKey)) {
        console.error(`分类 ${categoryKey} 不存在于 secondaryCategories 中`);
        console.error('当前 secondaryCategories 的键：', Object.keys(this.secondaryCategories));
        console.error('当前 categorizedAudioList 的键：', Object.keys(this.categorizedAudioList));
        this.$message.error("分类配置异常，请刷新页面");
        return;
      }
      
      // 确保 categorizedAudioList 中也有对应的分类
      if (!this.categorizedAudioList.hasOwnProperty(categoryKey)) {
        console.warn(`分类 ${categoryKey} 在音频列表中不存在，正在初始化...`);
        this.$set(this.categorizedAudioList, categoryKey, []);
      }

      const categoryName = categoryInfo.name;
      const categoryAudios = this.categorizedAudioList[categoryKey] || [];
      const audioCount = categoryAudios.length;

      // 构建确认消息
      let confirmMessage = `确定要删除分类"${categoryName}"吗？`;
      
      // 如果是系统分类，给出特别提醒
      if (!categoryKey.startsWith('custom_')) {
        confirmMessage += `\n\n⚠️ 这是系统分类，删除后将无法恢复！`;
      }
      
      if (audioCount > 0) {
        if (categoryKey === 'other') {
          confirmMessage += `\n\n该分类下有 ${audioCount} 个音频文件，删除分类后这些音频也将被彻底删除！`;
        } else {
          confirmMessage += `\n\n该分类下有 ${audioCount} 个音频文件，删除分类后这些音频将被移动到"其他音频"分类。`;
        }
      }

      uni.showModal({
        title: "确认删除分类",
        content: confirmMessage,
        confirmText: "确认删除",
        cancelText: "取消",
        confirmColor: "#ef4444",
        success: (res) => {
          if (res.confirm) {
            this.performDeleteCategory(categoryKey, categoryName, categoryAudios);
          }
        }
      });
    },

    // 执行删除分类操作
    async performDeleteCategory(categoryKey, categoryName, categoryAudios) {
      try {
        console.log(`开始删除分类：${categoryName}，包含 ${categoryAudios.length} 个音频`);
        
        // 验证数据完整性
        if (!this.secondaryCategories[categoryKey]) {
          throw new Error(`分类 ${categoryKey} 不存在于 secondaryCategories`);
        }
        
        if (!this.categorizedAudioList[categoryKey]) {
          throw new Error(`分类 ${categoryKey} 不存在于 categorizedAudioList`);
        }

        // 如果分类下有音频，需要处理音频去向
        if (categoryAudios.length > 0) {
          // 如果删除的就是"其他音频"分类，音频将被彻底删除
          if (categoryKey === 'other') {
            console.log('删除"其他音频"分类，同时删除其中的音频');
            // 从总列表中删除这些音频
            let deletedCount = 0;
            categoryAudios.forEach(deleteAudio => {
              const audioIndex = this.audioList.findIndex(audio => audio.id === deleteAudio.id);
              if (audioIndex !== -1) {
                this.audioList.splice(audioIndex, 1);
                deletedCount++;
              }
            });
            console.log(`从总列表中删除了 ${deletedCount} 个音频`);
          } else {
            console.log('将分类下的音频移动到"其他音频"分类');
            // 确保"其他音频"分类存在
            if (!this.categorizedAudioList.other) {
              this.categorizedAudioList.other = [];
            }
            
            // 其他分类的音频移动到"其他音频"分类
            let movedCount = 0;
            categoryAudios.forEach(audio => {
              audio.category = "其他";
              audio.secondaryCategory = "other";
              movedCount++;
            });

            // 将音频移动到"其他音频"分类
            this.categorizedAudioList.other.push(...categoryAudios);

            // 同步更新总列表中的音频分类
            let updatedCount = 0;
            this.audioList.forEach(audio => {
              if (categoryAudios.some(catAudio => catAudio.id === audio.id)) {
                audio.category = "其他";
                audio.secondaryCategory = "other";
                updatedCount++;
              }
            });
            console.log(`移动了 ${movedCount} 个音频，更新了 ${updatedCount} 个总列表项`);
          }
        }

        // 从分类列表中删除
        this.$delete(this.secondaryCategories, categoryKey);
        console.log(`从 secondaryCategories 删除分类：${categoryKey}`);
        
        // 从分类音频列表中删除
        this.$delete(this.categorizedAudioList, categoryKey);
        console.log(`从 categorizedAudioList 删除分类：${categoryKey}`);

        // 从分类选择器选项中删除
        const oldOptionsLength = this.categoryOptions.length;
        this.categoryOptions = this.categoryOptions.filter(
          option => option.value !== categoryName
        );
        console.log(`从分类选项中删除，原有 ${oldOptionsLength} 个，现有 ${this.categoryOptions.length} 个`);

        // 强制更新视图
        this.$forceUpdate();
        console.log('强制更新视图完成');

        console.log(`成功删除分类：${categoryName}，处理了${categoryAudios.length}个音频`);

        let successMessage = `分类"${categoryName}"已删除`;
        if (categoryAudios.length > 0) {
          if (categoryKey === 'other') {
            successMessage += `，${categoryAudios.length}个音频已同时删除`;
          } else {
            successMessage += `，${categoryAudios.length}个音频已移动到"其他音频"`;
          }
        }

        this.$message({
          message: successMessage,
          type: 'success',
          duration: 2000
        });

        // 调用后端API删除分类配置
        try {
          const audioAction = categoryKey === 'other' ? 'delete' : 'move';
          console.log('调用后端删除分类API，音频操作:', audioAction);
          
          const result = await deleteRoomCategory(this.currentRoom.id, categoryKey, audioAction);
          console.log('后端删除分类API响应:', result);
          
          this.$message({
            message: `分类删除成功！${result.data.audio_message}`,
            type: 'success',
            duration: 3000
          });
        } catch (apiError) {
          console.error('调用后端删除分类API失败:', apiError);
          this.$message({
            message: `删除成功，但同步到服务器失败：${apiError}`,
            type: 'warning',
            duration: 3000
          });
        }

      } catch (error) {
        console.error("删除分类时出错:", error);
        console.error("错误详情:", {
          message: error.message,
          stack: error.stack,
          categoryKey,
          categoryName,
          categoryAudiosLength: categoryAudios.length,
          secondaryCategoriesKeys: Object.keys(this.secondaryCategories),
          categorizedAudioListKeys: Object.keys(this.categorizedAudioList)
        });
        
        // 根据错误类型提供不同的用户提示
        let errorMessage = "删除失败，请重试";
        if (error.message.includes('不存在于')) {
          errorMessage = "分类数据异常，请刷新页面后重试";
        } else if (error.message.includes('其他音频')) {
          errorMessage = "音频转移失败，请检查\"其他音频\"分类";
        }
        
        this.$message({
          message: errorMessage,
          type: 'error',
          duration: 3000
        });
      }
    },

    // 获取默认分类名称
    getDefaultCategoryName(categoryType) {
      const defaultNames = {
        'scene': '场景音频',
        'background': '背景音乐', 
        'other': '其他音频'
      };
      return defaultNames[categoryType] || categoryType;
    },

    // 获取默认分类描述
    getDefaultCategoryDescription(categoryType) {
      const defaultDescriptions = {
        'scene': '欢迎语、感谢语、互动等场景音频',
        'background': '直播间背景音乐',
        'other': '未分类的音频文件'
      };
      return defaultDescriptions[categoryType] || `${categoryType}相关音频`;
    },

    // 获取默认分类图标
    getDefaultCategoryIcon(categoryType) {
      const defaultIcons = {
        'scene': '🎭',
        'background': '🎵',
        'other': '🎧'
      };
      return defaultIcons[categoryType] || '🎵';
    },

    // 获取默认分类子分类
    getDefaultCategorySubCategories(categoryType) {
      const defaultSubCategories = {
        'scene': ['欢迎语', '感谢语', '互动语', '活动语', '节日语', '提醒语'],
        'background': ['背景音乐'],
        'other': []
      };
      return defaultSubCategories[categoryType] || [];
    },
  },

  // 清理定时器避免内存泄漏
  beforeDestroy() {
    console.log('🧹 页面销毁，清理音量保存定时器');
    
    // 清理所有音频音量防抖定时器
    Object.keys(this.volumeSaveTimers).forEach(audioId => {
      if (this.volumeSaveTimers[audioId]) {
        clearTimeout(this.volumeSaveTimers[audioId]);
      }
    });
    this.volumeSaveTimers = {};

    // 清理所有分类音量防抖定时器
    Object.keys(this.categoryVolumeSaveTimers).forEach(categoryKey => {
      if (this.categoryVolumeSaveTimers[categoryKey]) {
        clearTimeout(this.categoryVolumeSaveTimers[categoryKey]);
      }
    });
    this.categoryVolumeSaveTimers = {};
  },
};
</script>

<style>
/* 基础样式 - PC端适配 */
.container {
  background: #f8f9fa;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 40rpx;
}

/* 头部信息 - PC端优化 */
.header-info {
  background: linear-gradient(135deg, #667eea, #764ba2);
  padding: 30rpx;
  color: #fff;
  position: relative;
  overflow: hidden;
  border-radius: 20rpx;
  margin: 20rpx 0;
}

.header-info::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: radial-gradient(
    circle at 80% 20%,
    rgba(255, 255, 255, 0.1) 0%,
    transparent 50%
  );
  pointer-events: none;
}

.room-info {
  position: relative;
  z-index: 1;
}

.room-name {
  display: block;
  font-size: 36rpx;
  font-weight: 600;
  color: #ffffff;
  margin-bottom: 8rpx;
}

.room-desc {
  display: block;
  font-size: 28rpx;
  color: #ffffff;
  opacity: 0.9;
}

/* 工具栏样式 */
.toolbar {
  padding: 0;
  margin: 20rpx;
}

.toolbar-card {
  background: #fff;
  border-radius: 12rpx;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}

.toolbar-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 30rpx;
  flex-wrap: wrap;
  gap: 20rpx;
}

.toolbar-info {
  flex: 1;
  min-width: 200rpx;
}

.playlist-title {
  font-size: 32rpx;
  font-weight: 600;
  color: #333;
  margin-bottom: 6rpx;
}

.playlist-hint {
  font-size: 24rpx;
  color: #666;
  opacity: 0.8;
  display: block;
}

/* 播放状态栏 */
.playing-status-bar {
  padding: 20rpx 40rpx;
  margin-bottom: 20rpx;
}

.status-card {
  background: linear-gradient(135deg, #ffffff, #f8fafc);
  border-radius: 16rpx;
  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
  border: 1rpx solid #e2e8f0;
  overflow: hidden;
  transition: all 0.3s ease;
}

.status-card:hover {
  box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.12);
  transform: translateY(-2rpx);
}

.status-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16rpx 20rpx;
  background: linear-gradient(135deg, #f1f5f9, #e2e8f0);
  border-bottom: 1rpx solid #cbd5e1;
}

.status-title-section {
  display: flex;
  align-items: center;
  gap: 12rpx;
}

.status-icon {
  font-size: 26rpx;
  animation: bounce 2s infinite;
}

.status-title {
  font-size: 24rpx;
  font-weight: 600;
  color: #1e293b;
}

.status-stats {
  display: flex;
  gap: 15rpx;
  align-items: center;
}

.stats-item {
  display: flex;
  align-items: center;
  gap: 6rpx;
  padding: 6rpx 12rpx;
  background: rgba(255, 255, 255, 0.8);
  border-radius: 16rpx;
  border: 1rpx solid rgba(148, 163, 184, 0.3);
  font-size: 20rpx;
}

.stats-label {
  font-size: 28rpx;
  color: #64748b;
  font-weight: 500;
}

.stats-value {
  font-size: 28rpx;
  font-weight: 700;
  color: #1e293b;
}

.stats-value.playing-count {
  color: #10b981;
  background: rgba(16, 185, 129, 0.1);
  padding: 2rpx 6rpx;
  border-radius: 6rpx;
  min-width: 32rpx;
  text-align: center;
}

.status-content {
  padding: 20rpx;
  min-height: 80rpx;
}

/* 播放内容区域 */
.playing-content {
  width: 100%;
}

.playing-cards-container {
  display: flex;
  flex-wrap: wrap;
  gap: 20rpx;
  align-items: flex-start;
  width: 100%;
  padding: 0 4rpx;
}

.playing-card {
  background: linear-gradient(145deg, #ffffff 0%, #fafafa 100%);
  border: 2rpx solid #e1e5e9;
  border-radius: 20rpx;
  padding: 24rpx 20rpx;
  flex: 0 0 calc(33.333% - 14rpx);
  width: calc(33.333% - 14rpx);
  max-width: calc(33.333% - 14rpx);
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  overflow: hidden;
  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
  box-sizing: border-box;
  cursor: pointer;
}

.playing-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 6rpx;
  height: 100%;
  background: linear-gradient(180deg, #667eea 0%, #764ba2 100%);
  animation: playingPulse 2s infinite;
  border-radius: 0 4rpx 4rpx 0;
}

.playing-card.card-primary {
  background: linear-gradient(145deg, #f8faff 0%, #eef2ff 100%);
  border: 2rpx solid #c7d2fe;
  box-shadow: 0 8rpx 30rpx rgba(99, 102, 241, 0.15), 0 2rpx 8rpx rgba(99, 102, 241, 0.1);
  transform: translateY(-2rpx);
}

.playing-card.card-primary::before {
  background: linear-gradient(180deg, #6366f1 0%, #8b5cf6 100%);
  width: 8rpx;
}

.playing-card:hover {
  transform: translateY(-4rpx);
  box-shadow: 0 12rpx 40rpx rgba(0, 0, 0, 0.12), 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
  border-color: #c7d2fe;
  background: linear-gradient(145deg, #fafbff 0%, #f1f5f9 100%);
}

.card-header {
  display: flex;
  align-items: center;
  gap: 12rpx;
  margin-bottom: 16rpx;
  padding-bottom: 12rpx;
  border-bottom: 1rpx solid #f1f5f9;
}

.category-icon {
  font-size: 28rpx;
  line-height: 1;
  filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.1));
}

.category-name {
  font-size: 22rpx;
  font-weight: 600;
  color: #1e293b;
  background: linear-gradient(135deg, #e0e7ff 0%, #c7d2fe 100%);
  padding: 6rpx 12rpx;
  border-radius: 12rpx;
  flex: 1;
  text-align: center;
  box-shadow: 0 2rpx 8rpx rgba(99, 102, 241, 0.15);
  border: 1rpx solid #c7d2fe;
}

.card-wave {
  display: flex;
  align-items: center;
  gap: 3rpx;
  padding: 4rpx 8rpx;
  background: rgba(34, 197, 94, 0.1);
  border-radius: 8rpx;
}

.wave-dot {
  width: 8rpx;
  height: 8rpx;
  background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
  border-radius: 50%;
  display: inline-block;
  animation: waveDot 1.8s infinite ease-in-out;
  font-size: 0;
  box-shadow: 0 2rpx 4rpx rgba(34, 197, 94, 0.3);
}

.wave-dot:nth-child(1) {
  animation-delay: 0s;
}

.wave-dot:nth-child(2) {
  animation-delay: 0.2s;
}

.wave-dot:nth-child(3) {
  animation-delay: 0.4s;
}

.card-content {
  display: flex;
  flex-direction: column;
  gap: 8rpx;
}

.card-title-row {
  display: flex;
  align-items: center;
  gap: 12rpx;
  margin-bottom: 12rpx;
}

.card-audio-index {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 50rpx;
}

.card-order-number {
  width: 36rpx;
  height: 36rpx;
  background: #667eea;
  color: #fff;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18rpx;
  font-weight: 600;
  flex-shrink: 0;
}

.card-order-number.playing {
  background: linear-gradient(135deg, #10b981, #059669);
  animation: pulse 2s infinite;
  box-shadow: 0 4rpx 15rpx rgba(16, 185, 129, 0.3);
}

.audio-name {
  font-size: 26rpx;
  font-weight: 600;
  color: #0f172a;
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: 0.5rpx;
  text-shadow: 0 1rpx 2rpx rgba(15, 23, 42, 0.1);
  flex: 1;
}

.audio-duration {
  font-size: 18rpx;
  color: #64748b;
  font-weight: 500;
  align-self: flex-end;
}

/* 空闲状态 */
.idle-content {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 80rpx;
  padding: 10rpx;
}

.idle-info {
  display: flex;
  align-items: center;
  gap: 15rpx;
  text-align: left;
  background: rgba(156, 163, 175, 0.08);
  padding: 15rpx 20rpx;
  border-radius: 12rpx;
  border: 1rpx dashed rgba(156, 163, 175, 0.3);
}

.idle-icon {
  font-size: 32rpx;
  opacity: 0.6;
  animation: float 3s ease-in-out infinite;
  flex-shrink: 0;
}

.idle-text {
  font-size: 22rpx;
  color: #64748b;
  font-weight: 500;
  margin-right: 8rpx;
}

.idle-hint {
  font-size: 20rpx;
  color: #9ca3af;
  flex: 1;
}

/* PC端工具栏优化 */
.toolbar-actions {
  display: flex;
  gap: 16rpx;
  flex-wrap: nowrap;
  justify-content: flex-end;
  align-items: center;
}

/* PC端工具栏按钮优化 */
.toolbar-btn {
  padding: 8rpx 16rpx;
  border: none;
  border-radius: 8rpx;
  font-size: 22rpx;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
  backdrop-filter: blur(10rpx);
  position: relative;
  overflow: hidden;
  min-width: 90rpx;
  white-space: nowrap;
  height: 60rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.toolbar-btn::before {
  content: "";
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(255, 255, 255, 0.2),
    transparent
  );
  transition: left 0.5s ease;
}

.toolbar-btn:hover::before {
  left: 100%;
}

.primary-btn {
  background: linear-gradient(135deg, #4f46e5, #7c3aed);
  color: white;
  border: none;
}

.primary-btn:hover {
  background: linear-gradient(135deg, #4338ca, #6d28d9);
  box-shadow: 0 8rpx 25rpx rgba(79, 70, 229, 0.4);
  transform: translateY(-2rpx);
}

.warning-btn {
  background: linear-gradient(135deg, #f59e0b, #d97706);
  color: white;
  border: none;
}

.warning-btn:hover {
  background: linear-gradient(135deg, #d97706, #b45309);
  box-shadow: 0 8rpx 25rpx rgba(245, 158, 11, 0.4);
  transform: translateY(-2rpx);
}

.info-btn {
  background: linear-gradient(135deg, #06b6d4, #0891b2);
  color: white;
  border: none;
}

.info-btn:hover {
  background: linear-gradient(135deg, #0891b2, #0e7490);
  box-shadow: 0 8rpx 25rpx rgba(6, 182, 212, 0.4);
  transform: translateY(-2rpx);
}

.success-btn {
  background: linear-gradient(135deg, #10b981, #059669);
  color: white;
  border: none;
}

.success-btn:hover {
  background: linear-gradient(135deg, #059669, #047857);
  box-shadow: 0 4rpx 15rpx rgba(16, 185, 129, 0.3);
  transform: translateY(-1rpx);
}

.danger-btn {
  background: linear-gradient(135deg, #ef4444, #dc2626);
  color: white;
  border: none;
}

.danger-btn:hover {
  background: linear-gradient(135deg, #dc2626, #b91c1c);
  transform: translateY(-1rpx);
  box-shadow: 0 4rpx 15rpx rgba(239, 68, 68, 0.3);
}

.toolbar-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* 音频列表区域 */
.audio-list-section {
  flex: 1;
  padding-bottom: 40rpx;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* 分类列表容器 - PC端优化 */
.category-list {
  width: 100%;
  height: calc(100vh - 280rpx);
  min-height: 400rpx;
  padding: 20rpx 40rpx;
  box-sizing: border-box;
}

/* 分类区域 */
.category-section {
  margin-bottom: 30rpx;
  background: #ffffff;
  border-radius: 16rpx;
  overflow: hidden;
  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
  transition: all 0.3s ease;
}

.category-section:hover {
  box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.12);
  transform: translateY(-2rpx);
}

/* 分类标题栏 - PC端优化 */
.category-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 30rpx 40rpx;
  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
  border-bottom: 2rpx solid #e2e8f0;
  cursor: pointer;
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
}

.category-header:hover {
  background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%);
}

.category-header::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 4rpx;
  height: 100%;
  background: linear-gradient(135deg, #667eea, #764ba2);
  transition: width 0.3s ease;
}

.category-header:hover::before {
  width: 8rpx;
}

.category-header-left {
  display: flex;
  align-items: center;
  gap: 20rpx;
  flex: 1;
  margin-right: 10rpx;
}

.category-icon {
  font-size: 40rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 60rpx;
  height: 60rpx;
  background: linear-gradient(
    135deg,
    rgba(102, 126, 234, 0.1),
    rgba(118, 75, 162, 0.1)
  );
  border-radius: 12rpx;
}

.category-title-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4rpx;
}

.category-title {
  font-size: 32rpx;
  font-weight: 600;
  color: #1e293b;
  display: block;
}

.category-description {
  font-size: 24rpx;
  color: #64748b;
  display: block;
  opacity: 0.8;
}

.category-status {
  display: flex;
  align-items: center;
  gap: 15rpx;
}

.category-count {
  font-size: 26rpx;
  color: #475569;
  background: rgba(100, 116, 139, 0.1);
  padding: 6rpx 12rpx;
  border-radius: 12rpx;
  font-weight: 500;
}

.playing-indicator {
  font-size: 22rpx;
  color: #10b981;
  background: linear-gradient(
    135deg,
    rgba(16, 185, 129, 0.15),
    rgba(5, 150, 105, 0.15)
  );
  padding: 8rpx 16rpx;
  border-radius: 20rpx;
  font-weight: 600;
  border: 1rpx solid rgba(16, 185, 129, 0.2);
}

.playing-indicator.pulse {
  animation: pulse 2s infinite;
}

/* PC端按钮组优化 */
.category-actions {
  display: flex;
  align-items: center;
  gap: 25rpx;
  flex-wrap: nowrap;
  justify-content: space-between;
  min-height: 50rpx;
}

/* 分类音量控制样式 */
.category-volume-control {
  display: flex;
  align-items: center;
  gap: 12rpx;
  margin-right: 20rpx;
  padding: 0;
  min-width: 200rpx;
}

.volume-label {
  font-size: 24rpx;
  color: #10b981;
  margin-right: 8rpx;
}

.clean-volume-slider {
  width: 320rpx;
  margin: 0;
}

.category-volume-display {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-left: 8rpx;
  min-width: 80rpx;
}

.category-volume-value {
  font-size: 20rpx;
  color: #374151;
  font-weight: 600;
  text-align: center;
  line-height: 1.2;
}

.category-volume-hint {
  font-size: 14rpx;
  color: #10b981;
  text-align: center;
  line-height: 1.2;
  margin-top: 2rpx;
}

/* PC端分类按钮组优化 */
.category-sort-group {
  display: flex;
  align-items: center;
  backdrop-filter: blur(10rpx);
  height: 75rpx;
  box-sizing: border-box;
}

.category-ctrl-group {
  display: flex;
  align-items: center;
  gap: 15rpx;
  height: 75rpx;
  box-sizing: border-box;
}

/* PC端按钮尺寸优化 */
.category-sort-btn,
.category-ctrl-btn,
.expand-btn {
  min-width: 120rpx;
  height: 55rpx;
  min-height: 55rpx;
  border-radius: 10rpx;
  border: none;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 3rpx 12rpx rgba(0, 0, 0, 0.1);
  backdrop-filter: blur(10rpx);
  position: relative;
  overflow: hidden;
  padding: 8rpx 16rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.category-sort-btn {
  background: linear-gradient(
    135deg,
    rgba(102, 126, 234, 0.9),
    rgba(118, 75, 162, 0.9)
  );
  color: white;
}

.category-sort-btn:hover {
  background: linear-gradient(135deg, #667eea, #764ba2);
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(102, 126, 234, 0.4);
}

.category-sort-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  transform: none !important;
  background: linear-gradient(135deg, #e5e7eb, #d1d5db) !important;
  color: #9ca3af !important;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1) !important;
}

/* 按钮内容布局 */
.btn-content {
  display: flex;
  align-items: center;
  gap: 8rpx;
  flex-direction: row;
}

/* PC端按钮文字优化 */
.btn-icon {
  font-size: 26rpx;
  line-height: 1;
}

.btn-text {
  font-size: 22rpx;
  font-weight: 500;
  white-space: nowrap;
  line-height: 1;
}

/* 展开按钮特定样式 */
.expand-btn {
  background: linear-gradient(
    135deg,
    rgba(100, 116, 139, 0.1),
    rgba(71, 85, 105, 0.1)
  );
  color: #475569;
  border: 1rpx solid rgba(100, 116, 139, 0.2);
}

.expand-btn:hover {
  background: linear-gradient(
    135deg,
    rgba(100, 116, 139, 0.2),
    rgba(71, 85, 105, 0.2)
  );
  transform: translateY(-2rpx);
  box-shadow: 0 6rpx 20rpx rgba(100, 116, 139, 0.3);
}

.expand-btn .btn-icon.expanded {
  transform: rotate(0deg);
}

/* 控制按钮的特定样式 */
.category-ctrl-btn.play-all-btn {
  background: linear-gradient(135deg, #10b981, #059669);
  color: white;
}

.category-ctrl-btn.play-all-btn:hover {
  background: linear-gradient(135deg, #059669, #047857);
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(16, 185, 129, 0.4);
}

.category-ctrl-btn.stop-btn {
  background: linear-gradient(135deg, #ef4444, #dc2626);
  color: white;
}

.category-ctrl-btn.stop-btn:hover {
  background: linear-gradient(135deg, #dc2626, #b91c1c);
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(239, 68, 68, 0.4);
}

.category-ctrl-btn.config-btn {
  background: linear-gradient(135deg, #6b7280, #4b5563);
  color: white;
}

.category-ctrl-btn.config-btn:hover {
  background: linear-gradient(135deg, #4b5563, #374151);
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(107, 114, 128, 0.4);
}

.category-ctrl-btn.delete-category-btn {
  background: linear-gradient(135deg, #f97316, #ea580c);
  color: white;
}

.category-ctrl-btn.delete-category-btn:hover {
  background: linear-gradient(135deg, #ea580c, #dc2626);
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(249, 115, 22, 0.4);
}

/* 播放中禁用删除按钮样式 */
.category-ctrl-btn.delete-category-btn.playing-disabled {
  background: linear-gradient(135deg, #9ca3af, #6b7280) !important;
  color: rgba(255, 255, 255, 0.7) !important;
  cursor: not-allowed !important;
  opacity: 0.5 !important;
  position: relative;
}

.category-ctrl-btn.delete-category-btn.playing-disabled:hover {
  background: linear-gradient(135deg, #9ca3af, #6b7280) !important;
  transform: none !important;
  box-shadow: 0 4rpx 15rpx rgba(156, 163, 175, 0.2) !important;
}

.category-ctrl-btn.delete-category-btn.playing-disabled::after {
  content: "🔊";
  position: absolute;
  top: -5rpx;
  right: -5rpx;
  width: 20rpx;
  height: 20rpx;
  background: #ef4444;
  color: white;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12rpx;
  animation: pulse 2s infinite;
}

.category-ctrl-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  transform: none !important;
  background: linear-gradient(135deg, #e5e7eb, #d1d5db) !important;
  color: #9ca3af !important;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1) !important;
}

/* 分类内容区域 */
.category-content {
  background: #ffffff;
  padding: 0;
}

/* 分类空状态 */
.category-empty {
  padding: 60rpx 30rpx;
  text-align: center;
  background: linear-gradient(135deg, #fafafa 0%, #f5f5f5 100%);
}

.empty-text {
  font-size: 28rpx;
  color: #9ca3af;
  margin-bottom: 10rpx;
  display: block;
}

.empty-hint {
  font-size: 24rpx;
  color: #cbd5e1;
  display: block;
  margin-top: 10rpx;
}

.empty-add-btn {
  background: linear-gradient(135deg, #6b7280, #4b5563);
  color: white;
  padding: 12rpx 24rpx;
  border-radius: 20rpx;
  border: none;
  font-size: 24rpx;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}

.empty-add-btn:hover {
  background: linear-gradient(135deg, #4b5563, #374151);
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 20rpx rgba(107, 114, 128, 0.3);
}

/* 音频项目 */
.audio-item {
  width: 100%;
  margin-bottom: 2rpx;
  background: #fff;
  border-radius: 0;
  box-shadow: none;
  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
  overflow: hidden;
  position: relative;
  border-bottom: 1rpx solid #f1f5f9;
}

.audio-item:last-child {
  border-bottom: none;
  border-radius: 0 0 16rpx 16rpx;
}

.audio-item:first-child {
  border-radius: 0;
}

.audio-item:hover {
  background: #fafbfc;
  border-color: #e2e8f0;
}

/* 播放状态的音频项目 */
.audio-item.playing {
  background: linear-gradient(
    135deg,
    rgba(16, 185, 129, 0.05) 0%,
    rgba(5, 150, 105, 0.05) 100%
  );
  border-left: 4rpx solid #10b981;
  animation: playingGlow 2s ease-in-out infinite alternate;
}

/* 高亮显示的音频项目 */
.audio-item.audio-highlighted {
  background: linear-gradient(
    135deg,
    rgba(59, 130, 246, 0.1) 0%,
    rgba(37, 99, 235, 0.1) 100%
  ) !important;
  border-left: 4rpx solid #3b82f6 !important;
  box-shadow: 0 0 20rpx rgba(59, 130, 246, 0.3) !important;
  animation: highlightPulse 0.8s ease-in-out 3 alternate;
  transform: translateX(8rpx);
}

.audio-item.playing .audio-name {
  color: #059669;
  font-weight: 600;
}

.audio-item.playing .order-number {
  background: linear-gradient(135deg, #10b981, #059669);
  animation: pulse 2s infinite;
  color: white;
  font-weight: 600;
}

@keyframes playingGlow {
  0% {
    box-shadow: 0 0 5rpx rgba(16, 185, 129, 0.2);
  }

  100% {
    box-shadow: 0 0 20rpx rgba(16, 185, 129, 0.4),
      0 0 30rpx rgba(16, 185, 129, 0.1);
  }
}

/* 移动模式样式 */
.audio-item.moving {
  background: linear-gradient(135deg, #8b5cf6, #a855f7);
  color: white;
  box-shadow: 0 8rpx 30rpx rgba(139, 92, 246, 0.5);
  transform: scale(1.02);
  border: 2rpx solid rgba(255, 255, 255, 0.3);
}

.audio-item.moving .audio-name,
.audio-item.moving .audio-category,
.audio-item.moving .audio-duration {
  color: white;
}

.audio-item.moving .order-number {
  background: rgba(255, 255, 255, 0.3);
  color: white;
}

.audio-item.move-target {
  opacity: 1;
  border: 2rpx dashed #8b5cf6;
  background: linear-gradient(
    135deg,
    rgba(139, 92, 246, 0.08),
    rgba(168, 85, 247, 0.08)
  );
  cursor: pointer;
  transition: all 0.3s ease;
}

.audio-item.move-target:hover {
  background: linear-gradient(
    135deg,
    rgba(139, 92, 246, 0.15),
    rgba(168, 85, 247, 0.15)
  );
  transform: scale(1.01);
  box-shadow: 0 6rpx 25rpx rgba(139, 92, 246, 0.3);
}

.audio-item.move-disabled {
  opacity: 0.4;
  cursor: not-allowed;
  background: #f5f5f5;
}

/* PC端音频内容区域优化 */
.audio-content {
  display: flex;
  align-items: center;
  gap: 20rpx;
  padding: 30rpx;
  min-height: 130rpx;
  box-sizing: border-box;
}

.audio-name {
  font-size: 30rpx;
  font-weight: 600;
  color: #333;
  margin-bottom: 8rpx;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.audio-category {
  background: #f0f0f0;
  color: #666;
  padding: 4rpx 12rpx;
  border-radius: 20rpx;
  font-size: 22rpx;
  margin-right: 15rpx;
}

.audio-duration {
  color: #667eea;
  font-size: 24rpx;
  font-weight: 500;
}

/* PC端操作按钮优化 */
.action-btn {
  padding: 10rpx 15rpx;
  border-radius: 12rpx;
  border: none;
  font-size: 26rpx;
  margin-left: 0;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
  min-width: 55rpx;
  height: 55rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4rpx 15rpx rgba(0, 0, 0, 0.1);
  backdrop-filter: blur(10rpx);
  position: relative;
  overflow: hidden;
}

.action-btn::before {
  content: "";
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(255, 255, 255, 0.2),
    transparent
  );
  transition: left 0.5s ease;
}

.action-btn:hover::before {
  left: 100%;
}

.play-btn {
  background: linear-gradient(135deg, #4f46e5, #7c3aed);
  color: white;
  border: none;
  min-width: 80rpx;
  padding: 12rpx 20rpx;
  white-space: nowrap;
}

.play-btn:hover {
  background: linear-gradient(135deg, #4338ca, #6d28d9);
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(79, 70, 229, 0.4);
}

.play-btn.pause-btn {
  background: linear-gradient(135deg, #f59e0b, #d97706);
}

.play-btn.pause-btn:hover {
  background: linear-gradient(135deg, #d97706, #b45309);
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(245, 158, 11, 0.4);
}


.delete-btn {
  background: linear-gradient(135deg, #ef4444, #dc2626);
  color: white;
  border: none;
}

.delete-btn:hover {
  background: linear-gradient(135deg, #dc2626, #b91c1c);
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(239, 68, 68, 0.4);
}

.move-btn {
  background: linear-gradient(135deg, #8b5cf6, #a855f7);
  color: white;
  border: none;
}

.move-btn:hover {
  background: linear-gradient(135deg, #7c3aed, #9333ea);
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(139, 92, 246, 0.4);
}

.preview-btn {
  background: linear-gradient(135deg, #06b6d4, #0891b2);
  color: white;
  border: none;
}

.preview-btn:hover {
  background: linear-gradient(135deg, #0891b2, #0e7490);
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(6, 182, 212, 0.4);
}

/* 播放状态指示 */
.playing-status {
  color: #10b981;
  font-size: 22rpx;
  font-weight: 600;
  background: linear-gradient(
    135deg,
    rgba(16, 185, 129, 0.1),
    rgba(5, 150, 105, 0.1)
  );
  padding: 4rpx 8rpx;
  border-radius: 8rpx;
  animation: pulse 2s infinite;
}

.cancel-btn {
  background: linear-gradient(135deg, #6b7280, #4b5563);
  color: white;
  border: none;
}

.cancel-btn:hover {
  background: linear-gradient(135deg, #4b5563, #374151);
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(107, 114, 128, 0.4);
}

.action-btn:active {
  transform: scale(0.95);
}

.action-btn:disabled {
  opacity: 0.3;
  cursor: not-allowed;
  background: #e0e0e0 !important;
  color: #999 !important;
  transform: none !important;
  box-shadow: none !important;
}

.empty-state {
  text-align: center;
  padding: 120rpx 50rpx;
  color: #64748b;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 1;
  min-height: 500rpx;
  background: linear-gradient(135deg, #fafbfc 0%, #f1f5f9 100%);
  border-radius: 20rpx;
  margin: 20rpx;
}

.empty-title {
  font-size: 36rpx;
  font-weight: 600;
  color: #475569;
  margin-bottom: 16rpx;
  display: block;
}

.empty-desc {
  font-size: 28rpx;
  color: #64748b;
  margin-bottom: 40rpx;
  display: block;
  opacity: 0.8;
}

.empty-main-btn {
  background: linear-gradient(135deg, #4f46e5, #7c3aed);
  color: white;
  padding: 24rpx 48rpx;
  border-radius: 30rpx;
  border: none;
  font-size: 30rpx;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 8rpx 30rpx rgba(79, 70, 229, 0.3);
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
}

.empty-main-btn::before {
  content: "";
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(255, 255, 255, 0.2),
    transparent
  );
  transition: left 0.5s ease;
}

.empty-main-btn:hover::before {
  left: 100%;
}

.empty-main-btn:hover {
  background: linear-gradient(135deg, #4338ca, #6d28d9);
  transform: translateY(-3rpx);
  box-shadow: 0 12rpx 40rpx rgba(79, 70, 229, 0.5);
}

/* 音频序号 */
.audio-index {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 60rpx;
}

.order-number {
  width: 40rpx;
  height: 40rpx;
  background: #667eea;
  color: #fff;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20rpx;
  font-weight: 600;
}

/* 音频信息 */
.audio-info {
  flex: 1;
  min-width: 0;
}

.audio-meta {
  display: flex;
  align-items: center;
  gap: 15rpx;
  margin-top: 8rpx;
}

/* PC端音频操作按钮优化 */
.audio-actions {
  display: flex;
  gap: 10rpx;
  flex-shrink: 0;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* 音频音量控制样式 */
.audio-volume-control {
  display: flex;
  align-items: center;
  gap: 8rpx;
  margin-right: 15rpx;
  padding: 0;
  min-width: 160rpx;
}

.volume-icon {
  font-size: 20rpx;
  color: #3b82f6;
  margin-right: 6rpx;
}

.clean-audio-volume-slider {
  width: 320rpx;
  margin: 0;
}

.volume-display {
  display: flex;
  align-items: center;
  margin-left: 16rpx;
  min-width: 50rpx;
}

.volume-percent {
  font-size: 18rpx;
  color: #374151;
  font-weight: 600;
  text-align: center;
}

/* 自定义状态指示区域 - 固定宽度防止布局跳动 */
.custom-status-area {
  width: 20rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: 6rpx;
}

.custom-indicator {
  font-size: 22rpx;
  color: #67C23A;
  line-height: 1;
  animation: fadeInScale 0.3s ease-out;
}

@keyframes fadeInScale {
  from {
    opacity: 0;
    transform: scale(0.5);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

.custom-indicator-placeholder {
  width: 20rpx;
  height: 22rpx;
  /* 透明占位元素 */
}

/* 重置按钮区域 - 固定宽度防止布局跳动 */
.reset-button-area {
  width: 40rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: 6rpx;
}

.reset-button {
  padding: 2rpx 4rpx !important;
  font-size: 22rpx !important;
  min-width: auto !important;
  width: 36rpx;
  height: 28rpx;
  animation: slideInRight 0.3s ease-out;
  transition: all 0.2s ease;
}

.reset-button:hover {
  background-color: rgba(64, 158, 255, 0.1) !important;
  transform: scale(1.1);
}

@keyframes slideInRight {
  from {
    opacity: 0;
    transform: translateX(10px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

/* 音量更新视觉反馈 */
.audio-item.volume-updated {
  background: linear-gradient(90deg, rgba(16, 185, 129, 0.1) 0%, rgba(16, 185, 129, 0.05) 100%);
  border-left: 3px solid #10b981;
  transform: translateX(2px);
  transition: all 0.3s ease;
}

.audio-item.volume-updated .volume-display {
  animation: volumePulse 0.6s ease-in-out;
}

@keyframes volumePulse {
  0% { transform: scale(1); }
  50% { transform: scale(1.1); }
  100% { transform: scale(1); }
}


/* 加载状态 */
.loading-state {
  text-align: center;
  padding: 120rpx 50rpx;
  color: #64748b;
  font-size: 28rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 1;
  min-height: 500rpx;
  background: linear-gradient(135deg, #fafbfc 0%, #f1f5f9 100%);
  border-radius: 20rpx;
  margin: 20rpx;
}

.loading-spinner {
  font-size: 60rpx;
  margin-bottom: 30rpx;
  animation: spin 1s linear infinite;
  color: #667eea;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

/* Element Dialog 配置样式 */
.category-config-dialog .el-dialog {
  border-radius: 12px;
  overflow: hidden;
}

.category-config-dialog .el-dialog__header {
  background: linear-gradient(135deg, #667eea, #764ba2);
  color: white;
  padding: 20px 24px;
  position: relative;
  overflow: hidden;
}

.category-config-dialog .el-dialog__header::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: radial-gradient(
    circle at 80% 20%,
    rgba(255, 255, 255, 0.1) 0%,
    transparent 50%
  );
  z-index: 0;
}

.category-config-dialog .el-dialog__title {
  color: white;
  position: relative;
  z-index: 1;
}

.category-config-dialog .el-dialog__headerbtn {
  top: 20px;
  right: 24px;
  z-index: 2;
}

.category-config-dialog .el-dialog__headerbtn .el-dialog__close {
  color: white;
  font-size: 18px;
}

.category-config-dialog .el-dialog__body {
  padding: 0;
  max-height: 70vh;
  overflow-y: auto;
}

.category-config-dialog .el-dialog__footer {
  background: #f8fafc;
  border-top: 1px solid #e2e8f0;
  padding: 20px 24px;
}

.dialog-title-wrapper {
  display: flex;
  align-items: center;
  gap: 12px;
  position: relative;
  z-index: 1;
}

.dialog-title-wrapper .config-icon {
  font-size: 24px;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
}

.dialog-title-wrapper .config-title-text {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.dialog-title-wrapper .config-title {
  font-size: 18px;
  font-weight: 600;
  color: white;
  line-height: 1.2;
}

.dialog-title-wrapper .config-subtitle {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.8);
  font-weight: 400;
  line-height: 1.2;
}

/* 添加分类弹窗 */
.add-category-dialog .el-dialog {
  border-radius: 12px;
  overflow: hidden;
}

.add-category-dialog .el-dialog__header {
  background: linear-gradient(135deg, #10b981, #059669);
  color: white;
  padding: 20px 24px;
  position: relative;
  overflow: hidden;
}

.add-category-dialog .el-dialog__header::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: radial-gradient(
    circle at 80% 20%,
    rgba(255, 255, 255, 0.1) 0%,
    transparent 50%
  );
  z-index: 0;
}

.add-category-dialog .el-dialog__title {
  color: white;
  position: relative;
  z-index: 1;
}

.add-category-dialog .el-dialog__headerbtn {
  top: 20px;
  right: 24px;
  z-index: 2;
}

.add-category-dialog .el-dialog__headerbtn .el-dialog__close {
  color: white;
  font-size: 18px;
}

.add-category-dialog .el-dialog__body {
  padding: 24px;
  max-height: 60vh;
  overflow-y: auto;
}

.add-category-dialog .el-dialog__footer {
  background: #f8fafc;
  border-top: 1px solid #e2e8f0;
  padding: 20px 24px;
}

/* popup-header 等旧样式已移除，使用 Element Dialog 样式 */

.form-section {
  margin-bottom: 35rpx;
}

.form-label {
  display: block;
  font-size: 28rpx;
  font-weight: 600;
  color: #1e293b;
  margin-bottom: 15rpx;
}

.input-wrapper {
  width: 100%;
  position: relative;
}

/* Element UI form input 容器样式 */
.form-input {
  width: 100%;
}

/* Element UI form input 内部样式覆盖 */
.form-input .el-input__inner {
  width: 100%;
  height: 80rpx;
  padding: 0 20rpx;
  border: 2rpx solid #e2e8f0;
  border-radius: 12rpx;
  font-size: 28rpx;
  line-height: 80rpx;
  color: #1e293b;
  background-color: #ffffff;
  box-sizing: border-box;
}

.form-input .el-input__inner:focus {
  border-color: #10b981;
  background: white;
  box-shadow: 0 0 0 3rpx rgba(16, 185, 129, 0.1);
}

/* Element UI form textarea 容器样式 */
.form-textarea {
  width: 100%;
}

/* Element UI form textarea 内部样式覆盖 */
.form-textarea .el-textarea__inner {
  width: 100%;
  min-height: 120rpx;
  padding: 20rpx;
  border: 2rpx solid #e2e8f0;
  border-radius: 12rpx;
  font-size: 26rpx;
  color: #1e293b;
  background-color: #ffffff;
  box-sizing: border-box;
}

.form-textarea .el-textarea__inner:focus {
  border-color: #10b981;
  background: white;
  box-shadow: 0 0 0 3rpx rgba(16, 185, 129, 0.1);
}

.icon-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 20rpx;
  padding: 25rpx;
  background: #f8fafc;
  border-radius: 12rpx;
  border: 2rpx solid #e2e8f0;
  max-height: 400rpx;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.icon-grid::-webkit-scrollbar {
  width: 8rpx;
}

.icon-grid::-webkit-scrollbar-track {
  background: rgba(0, 0, 0, 0.05);
  border-radius: 4rpx;
}

.icon-grid::-webkit-scrollbar-thumb {
  background: rgba(16, 185, 129, 0.3);
  border-radius: 4rpx;
}

.icon-grid::-webkit-scrollbar-thumb:hover {
  background: rgba(16, 185, 129, 0.5);
}

.icon-item {
  width: 80rpx;
  height: 80rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 16rpx;
  background: white;
  border: 2rpx solid #e2e8f0;
  cursor: pointer;
  transition: all 0.3s ease;
  position: relative;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}

.icon-item:hover {
  border-color: #10b981;
  transform: scale(1.05);
  box-shadow: 0 4rpx 15rpx rgba(16, 185, 129, 0.2);
}

.icon-item.active {
  border-color: #10b981;
  background: linear-gradient(135deg, rgba(16, 185, 129, 0.1), rgba(5, 150, 105, 0.1));
  transform: scale(1.1);
  box-shadow: 0 6rpx 20rpx rgba(16, 185, 129, 0.3);
}

.icon-item.active::after {
  content: "✓";
  position: absolute;
  top: -8rpx;
  right: -8rpx;
  width: 24rpx;
  height: 24rpx;
  background: #10b981;
  color: white;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16rpx;
  font-weight: 600;
}

.icon-text {
  font-size: 40rpx;
  line-height: 1;
}

/* popup-footer 及相关按钮样式已移除，使用 Element Dialog footer */

/* 分类配置弹窗已替换为 Element Dialog - 旧样式已移除 */

.config-content {
  flex: 1;
  overflow-y: auto;
  padding: 30rpx;
}

.config-section {
  margin-bottom: 40rpx;
  background: #fafbfc;
  border-radius: 16rpx;
  padding: 30rpx;
  border: 1rpx solid #e2e8f0;
}

.config-section-title {
  display: flex;
  align-items: center;
  gap: 15rpx;
  margin-bottom: 25rpx;
  font-size: 30rpx;
  font-weight: 600;
  color: #1e293b;
}

.section-icon {
  font-size: 32rpx;
}

.config-options {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20rpx;
}

.config-option {
  display: flex;
  align-items: center;
  gap: 15rpx;
  padding: 20rpx;
  background: white;
  border-radius: 12rpx;
  border: 2rpx solid #e2e8f0;
  cursor: pointer;
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
}

.config-option:hover {
  border-color: #667eea;
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(102, 126, 234, 0.15);
}

.config-option.active {
  border-color: #10b981;
  background: linear-gradient(
    135deg,
    rgba(16, 185, 129, 0.05),
    rgba(5, 150, 105, 0.05)
  );
  box-shadow: 0 8rpx 25rpx rgba(16, 185, 129, 0.2);
}

.config-option.active::before {
  content: "✓";
  position: absolute;
  top: 8rpx;
  right: 12rpx;
  color: #10b981;
  font-weight: 600;
  font-size: 24rpx;
}

.option-icon {
  font-size: 36rpx;
  width: 50rpx;
  height: 50rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(
    135deg,
    rgba(102, 126, 234, 0.1),
    rgba(118, 75, 162, 0.1)
  );
  border-radius: 10rpx;
}

.option-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4rpx;
}

.option-title {
  font-size: 28rpx;
  font-weight: 600;
  color: #1e293b;
  display: block;
}

.option-desc {
  font-size: 24rpx;
  color: #64748b;
  display: block;
  opacity: 0.8;
}

/* 输入框组样式 */
.config-input-group {
  background: white;
  border-radius: 12rpx;
  padding: 25rpx;
  border: 1rpx solid #e2e8f0;
}

/* 输入框行布局 */
.input-row {
  display: flex;
  align-items: flex-end;
  gap: 20rpx;
  margin-bottom: 25rpx;
}

.input-item {
  display: flex;
  flex-direction: column;
  gap: 15rpx;
}

.input-item.half-width {
  flex: 1;
  min-width: 120rpx;
}

.input-label {
  font-size: 28rpx;
  font-weight: 600;
  color: #1e293b;
}

.input-container {
  display: flex;
  align-items: center;
  gap: 15rpx;
  background: #f8fafc;
  border-radius: 12rpx;
  padding: 15rpx 20rpx;
  border: 2rpx solid #e2e8f0;
  transition: all 0.3s ease;
}

.input-container:focus-within {
  border-color: #667eea;
  background: white;
  box-shadow: 0 0 0 3rpx rgba(102, 126, 234, 0.1);
}

/* Element UI input-number 容器样式 */
.config-input {
  flex: 1;
}

/* Element UI input-number 内部样式覆盖 */
.config-input .el-input__inner {
  border: none;
  background: transparent;
  font-size: 26rpx;
  color: #1e293b;
  padding: 8rpx 0;
  text-align: center;
  font-weight: 600;
  height: auto;
}

/* Element UI input-number 控制按钮样式 */
.config-input .el-input-number__increase,
.config-input .el-input-number__decrease {
  background: #f8fafc;
  border: none;
  color: #64748b;
}

.config-input .el-input-number__increase:hover,
.config-input .el-input-number__decrease:hover {
  color: #1e293b;
  background: #e2e8f0;
}

.input-unit {
  font-size: 24rpx;
  color: #64748b;
  font-weight: 500;
  background: #e2e8f0;
  padding: 8rpx 12rpx;
  border-radius: 8rpx;
}

/* 间隔分隔符 */
.interval-separator {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 40rpx;
  height: 60rpx;
  margin-top: 35rpx;
}

.separator-text {
  font-size: 26rpx;
  color: #64748b;
  font-weight: 600;
  background: #f1f5f9;
  padding: 8rpx 12rpx;
  border-radius: 8rpx;
  border: 1rpx solid #e2e8f0;
}

/* 间隔预览 */
.interval-preview {
  display: flex;
  align-items: center;
  gap: 10rpx;
  margin-bottom: 15rpx;
  padding: 15rpx 20rpx;
  background: linear-gradient(135deg, rgba(16, 185, 129, 0.05), rgba(5, 150, 105, 0.05));
  border-radius: 12rpx;
  border: 1rpx solid rgba(16, 185, 129, 0.2);
}

.preview-label {
  font-size: 26rpx;
  color: #047857;
  font-weight: 600;
}

.preview-value {
  font-size: 26rpx;
  color: #059669;
  font-weight: 700;
  background: rgba(16, 185, 129, 0.1);
  padding: 6rpx 12rpx;
  border-radius: 8rpx;
}

/* 随机片段播放配置样式 */
.random-fragment-settings {
  margin-top: 25rpx;
  padding: 30rpx;
  background: linear-gradient(135deg, rgba(123, 97, 255, 0.05), rgba(99, 102, 241, 0.05));
  border-radius: 16rpx;
  border: 2rpx solid rgba(123, 97, 255, 0.15);
}

.fragment-preview {
  padding: 20rpx;
  background: linear-gradient(135deg, rgba(123, 97, 255, 0.08), rgba(99, 102, 241, 0.08));
  border-radius: 12rpx;
  border: 1rpx solid rgba(123, 97, 255, 0.2);
  margin-top: 20rpx;
}

.fragment-preview .preview-label {
  font-size: 26rpx;
  color: #6366f1;
  font-weight: 600;
}

.fragment-preview .preview-value {
  font-size: 26rpx;
  color: #4338ca;
  font-weight: 700;
  background: rgba(99, 102, 241, 0.1);
  padding: 6rpx 12rpx;
  border-radius: 8rpx;
  display: inline-block;
}

/* 片段策略选项样式 */
.fragment-strategy-options {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 15rpx;
  margin-top: 15rpx;
}

.strategy-option {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20rpx 15rpx;
  background: white;
  border-radius: 12rpx;
  border: 2rpx solid #e2e8f0;
  cursor: pointer;
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
  min-height: 100rpx;
}

.strategy-option:hover {
  border-color: #6366f1;
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(99, 102, 241, 0.15);
}

.strategy-option.active {
  border-color: #6366f1;
  background: linear-gradient(135deg, rgba(99, 102, 241, 0.08), rgba(123, 97, 255, 0.08));
  box-shadow: 0 8rpx 25rpx rgba(99, 102, 241, 0.2);
}

.strategy-option.active::before {
  content: "✓";
  position: absolute;
  top: 6rpx;
  right: 8rpx;
  color: #6366f1;
  font-weight: 600;
  font-size: 20rpx;
}

.strategy-icon {
  font-size: 32rpx;
  margin-bottom: 8rpx;
}

.strategy-name {
  font-size: 22rpx;
  font-weight: 600;
  color: #1e293b;
  text-align: center;
  line-height: 1.3;
}

/* 快捷设置样式 */
.fragment-quick-settings {
  margin-bottom: 25rpx;
  padding: 25rpx;
  background: linear-gradient(135deg, rgba(16, 185, 129, 0.03), rgba(5, 150, 105, 0.03));
  border-radius: 16rpx;
  border: 1rpx solid rgba(16, 185, 129, 0.1);
}

.quick-settings-label {
  font-size: 26rpx;
  font-weight: 600;
  color: #047857;
  margin-bottom: 15rpx;
  display: block;
}

.quick-settings-buttons {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12rpx;
}

.quick-setting-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 18rpx 12rpx;
  background: white;
  border-radius: 12rpx;
  border: 2rpx solid #e2e8f0;
  cursor: pointer;
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
  text-align: center;
}

.quick-setting-btn:hover {
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(0, 0, 0, 0.1);
}

.quick-setting-btn.conservative {
  border-color: #3b82f6;
}

.quick-setting-btn.conservative:hover {
  background: linear-gradient(135deg, rgba(59, 130, 246, 0.05), rgba(37, 99, 235, 0.05));
  border-color: #2563eb;
  box-shadow: 0 8rpx 25rpx rgba(59, 130, 246, 0.2);
}

.quick-setting-btn.balanced {
  border-color: #10b981;
}

.quick-setting-btn.balanced:hover {
  background: linear-gradient(135deg, rgba(16, 185, 129, 0.05), rgba(5, 150, 105, 0.05));
  border-color: #059669;
  box-shadow: 0 8rpx 25rpx rgba(16, 185, 129, 0.2);
}

.quick-setting-btn.aggressive {
  border-color: #f59e0b;
}

.quick-setting-btn.aggressive:hover {
  background: linear-gradient(135deg, rgba(245, 158, 11, 0.05), rgba(217, 119, 6, 0.05));
  border-color: #d97706;
  box-shadow: 0 8rpx 25rpx rgba(245, 158, 11, 0.2);
}

.quick-setting-btn.stealth {
  border-color: #8b5cf6;
}

.quick-setting-btn.stealth:hover {
  background: linear-gradient(135deg, rgba(139, 92, 246, 0.05), rgba(124, 58, 237, 0.05));
  border-color: #7c3aed;
  box-shadow: 0 8rpx 25rpx rgba(139, 92, 246, 0.2);
}

.preset-icon {
  font-size: 32rpx;
  margin-bottom: 8rpx;
}

.preset-name {
  font-size: 24rpx;
  font-weight: 600;
  color: #1e293b;
  margin-bottom: 4rpx;
  line-height: 1.2;
}

.preset-desc {
  font-size: 20rpx;
  color: #64748b;
  font-weight: 500;
  line-height: 1.2;
}

.input-hint {
  margin-top: 10rpx;
  padding: 12rpx 16rpx;
  background: linear-gradient(135deg, rgba(59, 130, 246, 0.05), rgba(37, 99, 235, 0.05));
  border-radius: 10rpx;
  border-left: 4rpx solid #3b82f6;
}

.hint-text {
  font-size: 22rpx;
  color: #1e40af;
  line-height: 1.5;
}

/* 保留滑块样式（其他地方可能用到） */
.config-slider-group {
  background: white;
  border-radius: 12rpx;
  padding: 25rpx;
  border: 1rpx solid #e2e8f0;
}

.slider-label {
  font-size: 32rpx;
  font-weight: 600;
  color: #667eea;
  text-align: center;
  display: block;
  margin-bottom: 20rpx;
}

.config-slider {
  width: 100%;
  margin: 20rpx 0;
}

.slider-range {
  display: flex;
  justify-content: space-between;
  font-size: 24rpx;
  color: #64748b;
  margin-top: 10rpx;
}

.config-switch-group {
  background: white;
  border-radius: 12rpx;
  padding: 25rpx;
  border: 1rpx solid #e2e8f0;
}

.switch-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20rpx;
}

.switch-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6rpx;
}

.switch-title {
  font-size: 30rpx;
  font-weight: 600;
  color: #1e293b;
  display: block;
}

.switch-desc {
  font-size: 24rpx;
  color: #64748b;
  display: block;
  opacity: 0.8;
}

.config-number-group {
  background: white;
  border-radius: 12rpx;
  padding: 25rpx;
  border: 1rpx solid #e2e8f0;
  display: flex;
  align-items: center;
  gap: 20rpx;
}

.number-label {
  font-size: 28rpx;
  color: #1e293b;
  font-weight: 500;
}

.number-controls {
  display: flex;
  align-items: center;
  gap: 15rpx;
  background: #f8fafc;
  border-radius: 30rpx;
  padding: 8rpx;
}

.number-btn {
  width: 40rpx;
  height: 40rpx;
  border-radius: 50%;
  border: none;
  background: linear-gradient(135deg, #667eea, #764ba2);
  color: white;
  font-size: 24rpx;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

.number-btn:hover {
  background: linear-gradient(135deg, #5a6fd8, #6b46a3);
  transform: scale(1.1);
}

.number-btn:disabled {
  background: #e5e7eb;
  color: #9ca3af;
  cursor: not-allowed;
  transform: none;
}

.number-value {
  font-size: 32rpx;
  font-weight: 600;
  color: #667eea;
  min-width: 60rpx;
  text-align: center;
}

.number-unit {
  font-size: 26rpx;
  color: #64748b;
}

/* config-footer 及相关按钮样式已移除，使用 Element Dialog footer */

/* PC端音频选择弹窗优化 */
.audio-picker {
  width: 95vw;
  height: 85vh;
  background: #fff;
  border-radius: 12rpx;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  max-width: 1800rpx;
  min-width: 1200rpx;
}

.picker-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 30rpx;
  border-bottom: 1rpx solid #eee;
  background: #fff;
}

.picker-title {
  font-size: 32rpx;
  font-weight: 600;
  color: #333;
}

.close-btn {
  width: 50rpx;
  height: 50rpx;
  border-radius: 50%;
  border: none;
  background: linear-gradient(135deg, #f1f5f9, #e2e8f0);
  color: #64748b;
  font-size: 30rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

.close-btn:hover {
  background: linear-gradient(135deg, #e2e8f0, #cbd5e1);
  color: #475569;
  transform: rotate(90deg);
}

.picker-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  height: 100%;
  min-height: 0;
}

/* 搜索筛选区域 */
.picker-filter {
  padding: 20rpx;
  background: #fafafa;
  border-bottom: 1rpx solid #eee;
  display: flex;
  gap: 15rpx;
  align-items: center;
  flex-wrap: nowrap;
}

/* Element UI input 容器样式 */
.search-input {
  flex: 2;
  min-width: 300rpx;
}

/* Element UI input 内部样式覆盖 */
.search-input .el-input__inner {
  padding: 18rpx 25rpx;
  border: 1rpx solid #ddd;
  border-radius: 10rpx;
  font-size: 28rpx;
  background: #fff;
  height: auto;
}

/* Element UI select 容器样式 */
.category-select {
  flex: 1;
  min-width: 200rpx;
  max-width: 400rpx;
}

/* Element UI select 内部样式覆盖 */
.category-select .el-input__inner {
  padding: 18rpx 25rpx;
  border: 1rpx solid #ddd;
  border-radius: 10rpx;
  font-size: 28rpx;
  background: #fff;
  color: #333;
  height: auto;
}

/* Element UI select 下拉选项样式 */
.category-select .el-select-dropdown__item {
  color: #333;
  background: #fff;
  padding: 12rpx 15rpx;
  white-space: nowrap;
  font-size: 28rpx;
}

.category-select .el-select-dropdown__item:hover {
  background: #f0f9ff;
}

.category-select .el-select-dropdown__item.selected {
  color: #333;
  background: #f0f9ff;
  font-weight: 500;
}

/* 可选音频列表 */
.available-list {
  flex: 1;
  padding: 0;
  overflow-y: auto;
  overflow-x: hidden;
  width: 100%;
  min-height: 0;
  max-height: 62vh;
}

/* PC端可用音频项目优化 */
.available-item {
  display: flex;
  align-items: center;
  gap: 35rpx;
  padding: 35rpx 30rpx;
  background: #fff;
  margin: 15rpx 20rpx 15rpx 20rpx;
  border-radius: 12rpx;
  transition: all 0.3s ease;
  cursor: pointer;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
  border: 1rpx solid #f0f0f0;
  min-height: 140rpx;
  box-sizing: border-box;
}

.available-item:hover {
  background: #f8f9fa;
  transform: translateY(-2rpx);
  box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.12);
  border-color: #667eea;
}

.available-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 15rpx;
  overflow: hidden;
}

.available-name {
  font-size: 32rpx;
  font-weight: 600;
  color: #333;
  word-break: break-all;
  line-height: 1.4;
  max-width: 100%;
  margin-bottom: 5rpx;
}

.available-meta {
  display: flex;
  align-items: center;
  gap: 25rpx;
  flex-wrap: wrap;
}

.available-category {
  background: #f0f0f0;
  color: #666;
  padding: 4rpx 12rpx;
  border-radius: 20rpx;
  font-size: 22rpx;
}

.available-duration {
  color: #667eea;
  font-size: 24rpx;
  font-weight: 500;
}

/* 播放进度样式 */
.play-progress {
  margin-top: 15rpx;
}

.loading-state {
  display: flex;
  align-items: center;
  gap: 10rpx;
}

.loading-text {
  color: #409EFF;
  font-size: 24rpx;
  animation: loading-fade 1.5s ease-in-out infinite;
}

@keyframes loading-fade {
  0%, 100% { opacity: 0.6; }
  50% { opacity: 1; }
}

.progress-container {
  display: flex;
  flex-direction: column;
  gap: 8rpx;
}

.progress-info {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.progress-time {
  color: #409EFF;
  font-size: 24rpx;
  font-weight: 500;
}

.progress-bar {
  width: 100%;
}

.progress-bg {
  width: 100%;
  height: 6rpx;
  background: #E4E7ED;
  border-radius: 3rpx;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #409EFF 0%, #67C23A 100%);
  border-radius: 3rpx;
  transition: width 0.3s ease;
}


/* 播放控制台卡片进度样式 */
.card-progress {
  margin-top: 16rpx;
  padding: 16rpx;
  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
  border-radius: 16rpx;
  border: 1rpx solid #e2e8f0;
  display: flex;
  flex-direction: column;
  gap: 12rpx;
}

.card-progress-bar {
  width: 100%;
  position: relative;
}

.card-progress-bg {
  width: 100%;
  height: 8rpx;
  background: linear-gradient(90deg, #e2e8f0 0%, #cbd5e1 100%);
  border-radius: 6rpx;
  overflow: hidden;
  box-shadow: inset 0 2rpx 4rpx rgba(0, 0, 0, 0.06);
  position: relative;
}

.card-progress-bg::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.8) 0%, rgba(255, 255, 255, 0.2) 100%);
  border-radius: 6rpx;
}

.card-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #6366f1 0%, #8b5cf6 50%, #ec4899 100%);
  border-radius: 6rpx;
  transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  min-width: 6rpx;
  position: relative;
  box-shadow: 0 2rpx 8rpx rgba(99, 102, 241, 0.4);
}

.card-progress-fill::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0.2) 100%);
  border-radius: 6rpx;
  animation: progressShimmer 2s infinite linear;
}

.card-progress-info {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12rpx;
}

.card-progress-time {
  color: #334155;
  font-size: 24rpx;
  font-weight: 600;
  font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
  text-shadow: 0 1rpx 2rpx rgba(255, 255, 255, 0.8);
  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
  padding: 6rpx 12rpx;
  border-radius: 8rpx;
  border: 1rpx solid #e2e8f0;
  box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.04);
}

.card-player-type {
  color: #ffffff;
  font-size: 20rpx;
  font-weight: 600;
  background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
  padding: 6rpx 16rpx;
  border-radius: 20rpx;
  box-shadow: 0 4rpx 12rpx rgba(99, 102, 241, 0.3);
  position: relative;
  overflow: hidden;
}

.card-player-type::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  animation: typeShimmer 2s infinite;
}

/* 下一首播放计划样式 */
.card-next-schedule {
  margin-top: 20rpx;
  padding: 20rpx;
  background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
  border: 1rpx solid #bae6fd;
  border-radius: 16rpx;
  display: flex;
  flex-direction: column;
  gap: 16rpx;
  animation: schedule-fade-in 0.3s ease-out;
}

@keyframes schedule-fade-in {
  from { opacity: 0; transform: translateY(10rpx); }
  to { opacity: 1; transform: translateY(0); }
}

.schedule-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16rpx;
}

.schedule-icon {
  font-size: 32rpx;
}

.schedule-label {
  font-size: 28rpx;
  font-weight: 600;
  color: #0369a1;
  flex: 1;
}

.schedule-countdown {
  display: flex;
  align-items: center;
  padding: 8rpx 16rpx;
  background: rgba(3, 105, 161, 0.1);
  border-radius: 12rpx;
  border: 1rpx solid rgba(3, 105, 161, 0.2);
}

.countdown-time {
  font-size: 28rpx;
  font-weight: 700;
  color: #0369a1;
  font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
  min-width: 40rpx;
  text-align: center;
  animation: countdown-pulse 1s ease-in-out infinite;
}

@keyframes countdown-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.7; }
}

.countdown-ready {
  font-size: 24rpx;
  color: #10b981;
  font-weight: 500;
  animation: ready-glow 1.5s ease-in-out infinite;
}

@keyframes ready-glow {
  0%, 100% { opacity: 0.8; }
  50% { opacity: 1; text-shadow: 0 0 8rpx rgba(16, 185, 129, 0.3); }
}

.schedule-content {
  display: flex;
  flex-direction: column;
  gap: 8rpx;
}

.schedule-audio-name {
  font-size: 30rpx;
  font-weight: 600;
  color: #1e40af;
  word-break: break-all;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.schedule-mode-info {
  font-size: 24rpx;
  color: #64748b;
  font-weight: 500;
  opacity: 0.8;
  display: flex;
  align-items: center;
  gap: 8rpx;
}

.schedule-mode-info::before {
  content: "⚙️";
  font-size: 20rpx;
}

/* 音频列表加载状态样式 */
.audio-list-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 100rpx 40rpx;
  gap: 30rpx;
}

.loading-spinner {
  display: flex;
  align-items: center;
  justify-content: center;
}

.spinner {
  width: 60rpx;
  height: 60rpx;
  border: 6rpx solid #E4E7ED;
  border-top: 6rpx solid #409EFF;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.audio-list-loading .loading-text {
  color: #409EFF;
  font-size: 28rpx;
  font-weight: 500;
}

/* 页面级加载状态样式 */
.page-loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

.page-loading-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 40rpx;
  padding: 60rpx;
  background: rgba(255, 255, 255, 0.95);
  border-radius: 20rpx;
  box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.1);
}

.spinner.large {
  width: 80rpx;
  height: 80rpx;
  border-width: 8rpx;
}

.spinner.small {
  width: 30rpx;
  height: 30rpx;
  border-width: 4rpx;
}

/* 分类选择器加载状态样式 */
.category-select-container {
  position: relative;
  display: flex;
  align-items: center;
  flex-shrink: 0;
  min-width: 200rpx;
}

/* Element UI select disabled 状态样式 */
.category-select.is-disabled .el-input__inner {
  opacity: 0.6;
  cursor: not-allowed;
  background-color: #f5f7fa;
  color: #c0c4cc;
}

.category-loading {
  position: absolute;
  right: 20rpx;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  pointer-events: none;
}

.page-loading-content .loading-text {
  color: #409EFF;
  font-size: 32rpx;
  font-weight: 600;
}

.available-actions {
  display: flex;
  gap: 15rpx;
  flex-shrink: 0;
  align-items: center;
  min-width: 120rpx;
}

.add-btn {
  background: linear-gradient(135deg, #06b6d4, #0891b2);
  color: white;
  border-radius: 10rpx;
  padding: 10rpx 16rpx;
  font-size: 24rpx;
  border: none;
  transition: all 0.3s ease;
}

.add-btn:hover {
  background: linear-gradient(135deg, #0891b2, #0e7490);
  transform: translateY(-2rpx);
  box-shadow: 0 8rpx 25rpx rgba(6, 182, 212, 0.4);
}

/* 插入区域样式优化 */
.insert-zone {
  margin: 20rpx 0;
  padding: 25rpx;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
  border-radius: 16rpx;
  background: linear-gradient(
    135deg,
    rgba(16, 185, 129, 0.08),
    rgba(5, 150, 105, 0.08)
  );
  border: 2rpx dashed rgba(16, 185, 129, 0.4);
  position: relative;
  overflow: hidden;
  box-shadow: 0 4rpx 20rpx rgba(16, 185, 129, 0.1);
}

/* 插入位置信息 */
.insert-position-info {
  margin-bottom: 15rpx;
  padding: 8rpx 16rpx;
  background: rgba(16, 185, 129, 0.1);
  border-radius: 20rpx;
  border: 1rpx solid rgba(16, 185, 129, 0.3);
}

.position-label {
  font-size: 24rpx;
  color: #047857;
  font-weight: 600;
  display: block;
}

.insert-zone:hover {
  background: linear-gradient(
    135deg,
    rgba(16, 185, 129, 0.1),
    rgba(5, 150, 105, 0.1)
  );
  border-color: rgba(16, 185, 129, 0.5);
  transform: scale(1.02);
  box-shadow: 0 8rpx 25rpx rgba(16, 185, 129, 0.2);
}

.insert-zone::before {
  content: "";
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(16, 185, 129, 0.1),
    transparent
  );
  transition: left 0.5s ease;
}

.insert-zone:hover::before {
  left: 100%;
}

.insert-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12rpx;
  padding: 20rpx 40rpx;
  background: linear-gradient(135deg, #10b981, #059669);
  color: white;
  border-radius: 30rpx;
  font-size: 26rpx;
  font-weight: 600;
  border: none;
  box-shadow: 0 8rpx 25rpx rgba(16, 185, 129, 0.3);
  transition: all 0.3s ease;
  position: relative;
  z-index: 1;
  min-width: 200rpx;
  margin-top: 5rpx;
}

.insert-btn:hover {
  background: linear-gradient(135deg, #059669, #047857);
  transform: translateY(-3rpx);
  box-shadow: 0 12rpx 35rpx rgba(16, 185, 129, 0.5);
}

.insert-icon {
    font-size: 26rpx;
  animation: bounceIcon 2s infinite;
}

.insert-text {
  font-size: 24rpx;
  font-weight: 600;
    white-space: nowrap;
  }

.top-insert {
  margin-top: 10rpx;
  margin-bottom: 25rpx;
  background: linear-gradient(
    135deg,
    rgba(59, 130, 246, 0.08),
    rgba(37, 99, 235, 0.08)
  );
  border-color: rgba(59, 130, 246, 0.4);
  box-shadow: 0 4rpx 20rpx rgba(59, 130, 246, 0.1);
}

.top-insert:hover {
  background: linear-gradient(
    135deg,
    rgba(59, 130, 246, 0.12),
    rgba(37, 99, 235, 0.12)
  );
  border-color: rgba(59, 130, 246, 0.6);
}

.top-insert .insert-position-info {
  background: rgba(59, 130, 246, 0.1);
  border-color: rgba(59, 130, 246, 0.3);
}

.top-insert .position-label {
  color: #1e40af;
}

.top-insert .insert-btn {
  background: linear-gradient(135deg, #3b82f6, #2563eb);
  box-shadow: 0 6rpx 20rpx rgba(59, 130, 246, 0.3);
}

.top-insert .insert-btn:hover {
  background: linear-gradient(135deg, #2563eb, #1d4ed8);
  box-shadow: 0 10rpx 30rpx rgba(59, 130, 246, 0.5);
}

.bottom-insert {
  margin-top: 30rpx;
  margin-bottom: 15rpx;
  background: linear-gradient(
    135deg,
    rgba(245, 158, 11, 0.08),
    rgba(217, 119, 6, 0.08)
  );
  border-color: rgba(245, 158, 11, 0.4);
  box-shadow: 0 4rpx 20rpx rgba(245, 158, 11, 0.1);
}

.bottom-insert:hover {
  background: linear-gradient(
    135deg,
    rgba(245, 158, 11, 0.12),
    rgba(217, 119, 6, 0.12)
  );
  border-color: rgba(245, 158, 11, 0.6);
}

.bottom-insert .insert-position-info {
  background: rgba(245, 158, 11, 0.1);
  border-color: rgba(245, 158, 11, 0.3);
}

.bottom-insert .position-label {
  color: #92400e;
}

.bottom-insert .insert-btn {
  background: linear-gradient(135deg, #f59e0b, #d97706);
  box-shadow: 0 6rpx 20rpx rgba(245, 158, 11, 0.3);
}

.bottom-insert .insert-btn:hover {
  background: linear-gradient(135deg, #d97706, #b45309);
  box-shadow: 0 10rpx 30rpx rgba(245, 158, 11, 0.5);
}

/* 插入按钮动画 */
@keyframes bounceIcon {
  0%, 20%, 50%, 80%, 100% {
    transform: translateY(0);
  }
  40% {
    transform: translateY(-4rpx);
  }
  60% {
    transform: translateY(-2rpx);
  }
}

/* 指示器样式 */
.moving-indicator {
  display: flex;
  align-items: center;
  gap: 8rpx;
    font-size: 20rpx;
  color: white;
  font-weight: 600;
  padding: 12rpx 18rpx;
  border-radius: 20rpx;
  background: linear-gradient(
    135deg,
    rgba(239, 68, 68, 0.9),
    rgba(220, 38, 38, 0.9)
  );
  backdrop-filter: blur(10rpx);
  border: 2rpx solid rgba(255, 255, 255, 0.4);
  animation: pulse 2s infinite;
  box-shadow: 0 4rpx 15rpx rgba(239, 68, 68, 0.4);
}

.moving-icon {
    font-size: 20rpx;
  animation: blink 1s infinite;
}

.moving-text {
  font-size: 18rpx;
  font-weight: 600;
  white-space: nowrap;
}

/* 取消移动按钮样式优化 */
.cancel-move-btn {
  min-width: 160rpx !important;
  height: 56rpx !important;
  font-size: 24rpx !important;
  padding: 8rpx 16rpx !important;
  flex-shrink: 0;
}

.target-indicator {
    display: flex;
  align-items: center;
    gap: 8rpx;
    font-size: 18rpx;
  color: #059669;
  font-weight: 500;
  padding: 10rpx 16rpx;
  border-radius: 18rpx;
  background: linear-gradient(135deg, rgba(16, 185, 129, 0.1), rgba(5, 150, 105, 0.1));
  border: 2rpx solid rgba(16, 185, 129, 0.3);
  cursor: pointer;
  transition: all 0.3s ease;
}

.target-indicator:hover {
  background: linear-gradient(135deg, rgba(16, 185, 129, 0.2), rgba(5, 150, 105, 0.2));
  border-color: rgba(16, 185, 129, 0.5);
  transform: scale(1.05);
}

.target-icon {
  font-size: 18rpx;
  animation: bounce 2s infinite;
}

.target-text {
  font-size: 16rpx;
  font-weight: 600;
  white-space: nowrap;
}

.disabled-indicator {
  display: flex;
  align-items: center;
  gap: 6rpx;
  font-size: 16rpx;
  color: #9ca3af;
  padding: 8rpx 12rpx;
  border-radius: 12rpx;
  background: linear-gradient(135deg, #f9fafb, #f3f4f6);
  border: 1rpx solid #e5e7eb;
  opacity: 0.6;
}

.disabled-icon {
  font-size: 16rpx;
}

.disabled-text {
  font-size: 14rpx;
  white-space: nowrap;
}

/* 指示器动画 */
@keyframes blink {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0.3; }
}

@keyframes bounce {
  0%, 20%, 50%, 80%, 100% {
    transform: translateY(0);
  }
  40% {
    transform: translateY(-4rpx);
  }
  60% {
    transform: translateY(-2rpx);
  }
}

/* 动画效果 */
@keyframes slideInDown {
  from {
    transform: translateY(-100%);
    opacity: 0;
  }

  to {
    transform: translateY(0);
    opacity: 1;
  }
}

@keyframes slideInUp {
  from {
    transform: translateY(50px);
    opacity: 0;
  }

  to {
    transform: translateY(0);
    opacity: 1;
  }
}

@keyframes fadeInUp {
  from {
    transform: translateY(20px);
    opacity: 0;
  }

  to {
    transform: translateY(0);
    opacity: 1;
  }
}

/* 按钮动效 */
.u-button {
  transition: all 0.3s ease;
}

.u-button:active {
  transform: scale(0.95);
}

/* 卡片动效 */
.u-card {
  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
  animation: fadeInUp 0.6s ease;
}

.u-card:hover {
  transform: translateY(-4rpx);
  box-shadow: 0 8rpx 25rpx rgba(0, 0, 0, 0.15);
}


/* 滚动条美化 */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 3px;
}

::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

/* 加载动效 */
.loading {
  animation: pulse 2s infinite;
}

@keyframes pulse {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }

  50% {
    opacity: 0.8;
    transform: scale(1.05);
  }
}

/* 过渡动画 */
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s ease;
}

.fade-enter,
.fade-leave-to {
  opacity: 0;
}

/* 弹窗动效 */
.u-popup {
  animation: bounceIn 0.5s ease;
}

@keyframes bounceIn {
  0% {
    transform: scale(0.3);
    opacity: 0;
  }

  50% {
    transform: scale(1.05);
  }

  70% {
    transform: scale(0.9);
  }

  100% {
    transform: scale(1);
    opacity: 1;
  }
}

/* 播放区域闪烁动画 */
@keyframes playingShimmer {
  0% {
    left: -100%;
  }
  50% {
    left: 100%;
  }
  100% {
    left: 100%;
  }
}

/* 波形动画 */
@keyframes waveAnimation {
  0%, 100% {
    height: 8rpx;
    opacity: 0.6;
  }
  50% {
    height: 20rpx;
    opacity: 1;
  }
}

/* 播放脉冲动画 */
@keyframes playingPulse {
  0% {
    opacity: 1;
    width: 4rpx;
  }
  50% {
    opacity: 0.7;
    width: 6rpx;
  }
  100% {
    opacity: 1;
    width: 4rpx;
  }
}

/* 浮动动画 */
@keyframes float {
  0%, 100% {
    transform: translateY(0px);
  }
  50% {
    transform: translateY(-10rpx);
  }
}

/* 波点动画 */
@keyframes waveDot {
  0%, 60%, 100% {
    transform: scale(1) translateY(0);
    opacity: 0.7;
  }
  30% {
    transform: scale(1.4) translateY(-2rpx);
    opacity: 1;
  }
}

@keyframes progressShimmer {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(200%);
  }
}

@keyframes typeShimmer {
  0% {
    left: -100%;
  }
  100% {
    left: 100%;
  }
}

/* 高亮脉冲动画 */
@keyframes highlightPulse {
  0% {
    box-shadow: 0 0 10rpx rgba(59, 130, 246, 0.2);
    transform: translateX(4rpx);
  }
  50% {
    box-shadow: 0 0 30rpx rgba(59, 130, 246, 0.5);
    transform: translateX(12rpx);
  }
  100% {
    box-shadow: 0 0 10rpx rgba(59, 130, 246, 0.2);
    transform: translateX(4rpx);
  }
}

/* 音频多选功能样式 */
.multi-select-toolbar {
  padding: 15rpx 20rpx;
  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
  border-bottom: 1rpx solid #e2e8f0;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.select-all-section {
  display: flex;
  align-items: center;
  gap: 20rpx;
}

.select-all-btn {
  padding: 8rpx 16rpx;
  background: linear-gradient(135deg, #3b82f6, #2563eb);
  color: white;
  border: none;
  border-radius: 8rpx;
  font-size: 24rpx;
  cursor: pointer;
  transition: all 0.3s ease;
  font-weight: 500;
}

.select-all-btn:hover {
  background: linear-gradient(135deg, #2563eb, #1d4ed8);
  transform: translateY(-1rpx);
}

.selected-count {
  font-size: 24rpx;
  color: #64748b;
  font-weight: 500;
}

/* 音频项选择框 */
.selection-checkbox {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 40rpx;
}

.checkbox-icon {
  width: 40rpx;
  height: 40rpx;
  border: 2rpx solid #d1d5db;
  border-radius: 8rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  background: white;
  transition: all 0.3s ease;
  cursor: pointer;
}

.checkbox-icon.checked {
  background: linear-gradient(135deg, #10b981, #059669);
  border-color: #10b981;
  color: white;
}

.check-mark {
  font-size: 24rpx;
  font-weight: 600;
  line-height: 1;
}

/* 选中状态的音频项 */
.available-item.selected {
  background: linear-gradient(135deg, rgba(16, 185, 129, 0.05), rgba(5, 150, 105, 0.05));
  border-left: 4rpx solid #10b981;
}

.available-item.selected:hover {
  background: linear-gradient(135deg, rgba(16, 185, 129, 0.08), rgba(5, 150, 105, 0.08));
}

/* 顶部分类选择器 - 显眼位置 */
.category-selector-top {
  padding: 20rpx;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 12rpx;
  margin: 20rpx 0;
  display: flex;
  align-items: center;
  gap: 20rpx;
  box-shadow: 0 8rpx 25rpx rgba(102, 126, 234, 0.3);
  animation: slideInDown 0.3s ease-out;
}

.selector-header {
  display: flex;
  align-items: center;
  gap: 8rpx;
}

.selector-icon {
  font-size: 18px;
}

.selector-title {
  font-size: 16px;
  color: #ffffff;
  font-weight: 600;
  white-space: nowrap;
}

.selected-info {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.9);
  background: rgba(255, 255, 255, 0.2);
  padding: 8rpx 16rpx;
  border-radius: 20rpx;
  margin-left: auto;
  font-weight: 500;
}

@keyframes slideInDown {
  from {
    opacity: 0;
    transform: translateY(-20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 原有的分类选择器 - 保持兼容 */
.category-selector {
  padding: 15rpx 20rpx;
  background: #f8fafc;
  border-top: 1rpx solid #e2e8f0;
  border-bottom: 1rpx solid #e2e8f0;
  display: flex;
  align-items: center;
  gap: 15rpx;
  flex-shrink: 0;
}

.selector-label {
  font-size: 14px;
  color: #64748b;
  font-weight: 500;
  white-space: nowrap;
}

/* 底部操作栏 */
.picker-footer {
  padding-top: 20rpx;
  background: #fff;
  border-top: 1rpx solid #e2e8f0;
  display: flex;
  gap: 15rpx;
  align-items: center;
  justify-content: flex-end;
  box-shadow: 0 -4rpx 15rpx rgba(0, 0, 0, 0.1);
  flex-shrink: 0;
  position: relative;
  z-index: 1;
}

.footer-btn {
  padding: 12rpx 24rpx;
  border: none;
  border-radius: 10rpx;
  font-size: 26rpx;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
  min-width: 120rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.footer-btn.cancel-btn {
  background: linear-gradient(135deg, #6b7280, #4b5563);
  color: white;
}

.footer-btn.cancel-btn:hover {
  background: linear-gradient(135deg, #4b5563, #374151);
  transform: translateY(-1rpx);
}

.footer-btn.clear-btn {
  background: linear-gradient(135deg, #ef4444, #dc2626);
  color: white;
}

.footer-btn.clear-btn:hover {
  background: linear-gradient(135deg, #dc2626, #b91c1c);
  transform: translateY(-1rpx);
}

.footer-btn.confirm-btn {
  background: linear-gradient(135deg, #10b981, #059669);
  color: white;
}

.footer-btn.confirm-btn:hover {
  background: linear-gradient(135deg, #059669, #047857);
  transform: translateY(-1rpx);
}

.footer-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none !important;
  background: linear-gradient(135deg, #e5e7eb, #d1d5db) !important;
  color: #9ca3af !important;
}

/* Element UI 自定义样式 */
.audio-picker-dialog {
  border-radius: 12px;
  max-height: 80vh;
  overflow: hidden;
}

.audio-picker-dialog .el-dialog__header {
  background: linear-gradient(135deg, #667eea, #764ba2);
  color: white;
  padding: 20px 30px;
  flex-shrink: 0;
}

.audio-picker-dialog .el-dialog__title {
  color: white;
  font-weight: 600;
}

.audio-picker-dialog .el-dialog__close {
  color: white;
  font-size: 18px;
}

.audio-picker-dialog .el-dialog__close:hover {
  color: #f0f0f0;
}

.audio-picker-dialog .el-dialog__body {
  padding: 0;
  height: calc(90vh - 140px);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* Element UI 按钮组样式优化 */
.category-sort-group .el-button-group .el-button {
  border-radius: 6px;
  font-size: 12px;
  padding: 8px 12px;
  margin: 0;
}

.category-ctrl-group .el-button-group .el-button {
  border-radius: 6px;
  font-size: 12px;
  padding: 8px 12px;
}

/* 工具栏Element UI按钮样式 */
.toolbar-actions .el-button {
  border-radius: 8px;
  font-weight: 500;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: all 0.3s ease;
}

.toolbar-actions .el-button:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
}

/* 分类操作按钮的Element UI样式 */
.category-actions .el-button {
  font-size: 12px;
  padding: 6px 12px;
  border-radius: 6px;
}

.category-actions .el-button-group .el-button:first-child {
  border-top-left-radius: 6px;
  border-bottom-left-radius: 6px;
}

.category-actions .el-button-group .el-button:last-child {
  border-top-right-radius: 6px;
  border-bottom-right-radius: 6px;
}

/* 音频操作按钮的Element UI样式 */
.audio-actions .el-button {
  width: 32px;
  height: 32px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 弹窗底部按钮样式 */
.picker-footer .el-button {
  border-radius: 8px;
  padding: 10px 20px;
  font-weight: 500;
}

/* 多选操作栏按钮样式 */
.multi-select-toolbar .el-button {
  border-radius: 6px;
  font-size: 14px;
}

/* Element UI Message 全局样式调整 */
.el-message {
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}

</style>
